Java Database Programming with JDBC Java Database Programming with JDBC
by Pratik Patel
Coriolis, The Coriolis Group
ISBN: 1576100561   Pub Date: 10/01/96
  

Table of Contents


APPENDIX C
DB2 JDBC Driver Source Code

As a bonus, a DB2 format JDBC driver is included on the CD-ROM. If you are still unclear about implementation issues surrounding the writing of JDBC drivers, read on. In this appendix, the full source code for the DB2 driver is listed. All of the classes for the driver are listed here except for the DB2DatabaseMetaData class, which is on the CD-ROM and Web site, as well as the source code for the other classes. This JDBC driver uses native methods, and it provides a valuable example of how you can incorporate existing database library files to quickly make a JDBC driver via native methods. Heiner Braun is the author of this driver, and while it is still under development, it is fully functional. He can be reached at braunhr@minnie.informatik.uni-stuttgart.de.

Listing C.1 DB2Driver.java.

/*    db2jdbc.sql.DB2Driver
 *
 *    Copyright (c) 1996 Heiner Braun
 *    Based on mSQL stuff by George Reese
 *    (borg&imaginary.com)
 *    as well as the JDBC specification v0.70.
 *    Left original comments; my comments are marked with
 *    _hb_.
 *    A JDBC compliant DB2 driver.
 */
package db2jdbc.sql;
import  java.sql.Connection;
import  java.sql.SQLException;
import    java.sql.DriverPropertyInfo;
import   java.util.Properties;
public class DB2Driver implements java.sql.Driver {
  /**
    * Constructs a new driver and registers it with
    * java.sql.DriverManager.registerDriver() as specified by the JDBC
    * draft protocol.
    */
   public DB2Driver() throws SQLException {
           java.sql.DriverManager.registerDriver(this);
  }

  /**
    * Takes a look at the given URL to see if it is meant for this
    * driver.  If not, simply return null.  If it is, then go ahead and
    * connect to the database.  For the mSQL implementation of JDBC, it
    * looks for URL's in the form of <P>
    * <PRE>
    * _hb_ currently the DB2Driver accepts:
    * _hb_ jdbc:db2local:[db_name]
    * _hb_ later the following should be accepted (see p.18 JDBC spec):
    * _hb_ [db_name] is optional
    * _hb_ jdbc:db2local:[db_name];UID=...;PWD=...
    *      jdbc:msql://[host_addr]:[port]/[db_name]
    * </PRE>
    * &see java.sql.Driver#connect
    * &param url the URL for the database in question
    * &param info the properties object
    * &return null if the URL should be ignored, a new Connection
    * implementation if the URL is a valid mSQL URL
    */
   public Connection connect(String url, Properties info)
       throws SQLException {
       if( ! url.substring(5,13).equals("db2local") ) return null;
    // _hb_ pass on thrown SQLExceptions...
      return new DB2Connection(info.getProperty("user"),
                      info.getProperty("password"),
                      url.substring(14));
  }

  /**
    * Returns true if the driver thinks that it can open a connection
    * to the given URL.  Typically, drivers will return true if they
    * understand the sun-protocol specified in the URL, and false
    * otherwise.
    *
    * &param url the URL of the database
    * &return true if this driver can connect to the given URL
    */
   public boolean acceptsURL(String url) throws SQLException {
      if( ! url.substring(5,13).equals("db2local") ) return false;
    // _hb_ URLs won't be supported
      return true;
  }

  /**
    * <p>The getPropertyInfo method is intended to allow a generic GUI
    * tool to discover what properties it should prompt a human for in
    * order to get enough information to connect to a database.  Note that
    * depending on the values the human has supplied so far, additional
    * values may become necessary, so it may be necessary to iterate
    * though several calls to get PropertyInfo.
    *
    * &param url the URL of the database to connect to
    * &param info a proposed list of tag/value pairs that will be sent on
    * connect open
    * &return an array of DriverPropertyInfo objects describing possible
    * properties; this array may be an empty array if no
    * properties are required
    */
   public DriverPropertyInfo[] getPropertyInfo(String url,
    java.util.Properties info)
    throws SQLException {

    // _hb_ what does empty array really mean?
      return null;
  }

  /**
    * Gives the major version for this driver as required by the JDBC
    * draft specification.
    * &see java.sql.Driver#getMajorVersion
    * &return the major version
    */
   public int getMajorVersion() {
      return 0;
  }

  /**
    * Gives the minor version for this driver as required by the JDBC
    * draft specification.
    * &see java.sql.Driver#getMinorVersion
    * &return the minor version
    */
   public int getMinorVersion() {
       return 1;
  }

  /**
    * Report whether the Driver is a genuine JDBC COMPLIANT (tm) driver.
    * A driver may only report "true" here if it passes the JDBC
    * compliance tests, otherwise it is required to return false.
    *
    * JDBC compliance requires full support for the JDBC API and full
    * support for SQL-92 Entry Level.  It is expected that JDBC compliant
    * drivers will be available for all the major commercial databases.
    *
    * This method is not intended to encourage the development of non-JDBC
    * compliant drivers, but is a recognition of the fact that some
    * vendors are interested in using the JDBC API and framework for
    * lightweight databases that do not support full database
    * functionality, or for special databases, such as document information
    * retrieval, where a SQL implementation may not be feasible.
    */
   public boolean jdbcCompliant() {
      return false;
  }
}

Listing C.2 DB2Connection.java.

/*    db2jdbc.sql.DB2Connection
 *
 *    Copyright (c) 1996 Heiner Braun
 *    Based on mSQL stuff by George Reese (borg&imaginary.com).
 *    Left (some) original comments; my comments are marked with _hb_.
 *     A DB2 implementation of the JDBC specification Connection interface.
 */
package db2jdbc.sql;
import  java.sql.CallableStatement;
import  java.sql.DatabaseMetaData;
// _hb_ import java.sql.Driver;
import  java.sql.PreparedStatement;
import  java.sql.SQLException;
import  java.sql.SQLWarning;
import  java.sql.Statement;
import  db2jdbc.sql.db2access.DB2CLI;
import  db2jdbc.sql.db2access.DB2CLIException;

public class DB2Connection implements java.sql.Connection {
  /**
    * DB2CLI object
    */
  private DB2CLI db2CLI = null;
  /**
    * The JDBC driver for this connection
    */
  // _hb_ private Driver driver;
  /**
    * The URL for this connection
    * _hb_ not needed?
    */
  private String url;
  /**
    * Catalog string that has no meaning to mSQL
    */
  private String catalog;
  /**
    * Transaction isolation level, meaningless to mSQL
    */
  private int isolation;
  /**
    * Constructs a new JDBC draft specification connection object for the
    * mSQL database.  Creates an instance of Darryl Collins' mSQL class
    * and uses it to connect to the named database on the named host.
    * &exception SQLException raised in the event of connection failure
    * &param host the IP address of the host on which the mSQL server
    * resides
    * &param root true if this is a root connection, false if otherwise
    * &param database the database to which a connection should
    * be made
    * &param u the URL used to connect to this database
    * &param d the driver that instantiated this connection
    */
   public DB2Connection(String user, String passwd,
                         String database)
       throws SQLException {

    catalog = database;
    db2CLI = new DB2CLI();
    // if( user == null || user == "" ) user = "nobody";
    try {
      db2CLI.getEnv();
      db2CLI.openConnection(user, passwd, database);
    }
    catch( DB2CLIException e ) {
      db2CLI = null;
      throw new SQLException("DB2CLI exception: " + e.getMessage());
    }
  }

  /**
    * JDBC draft specification method for returning a SQL statement
    * object.
    * &see java.sql.Connection#createStatement
    * &exception SQLException thrown in the event the creation fails
    * &return a new statement object
    */
   public Statement createStatement() throws SQLException {
    return new DB2Statement(this);
  }

  /**
    * JDBC draft specification method for returning an SQL pre-compiled
    * statement.  Note that mSQL does not support such things, so this
    * thing just throws an exception.
    * &see java.sql.Connection#prepareStatement
    * &exception SQLException gets thrown any time this is called
    */
   public PreparedStatement prepareStatement(String sql)
        throws SQLException {
     throw new SQLException("Prepared statements are not yet supported.");
  }

  /**
    * JDBC draft specification method for creating a stored procedure
    * call. Note that mSQL does not support stored procedures, so this
    * method throws an exception.
    * &see java.sql.Connection#prepareCall
    * &exception SQLException gets thrown any time this is called
    */
   public CallableStatement prepareCall(String sql)
       throws SQLException {
     throw new SQLException("Stored procedures are not yet supported.");
  }

  /**
    * JDBC draft specification method for converting generic SQL into
    * mSQL specific SQL.  Such a task would be mind-boggling, given the
    * fact that mSQL supports such a small subset of ANSI SQL.  This
    * method therefore simply returns the original and hopes for the best.
    * &see java.sql.Connection#nativeSQL
    * &param sql the query which just gets thrown right back out
    * &return the mSQL SQL string
    */
   public String nativeSQL(String sql) throws SQLException {
      return sql;
  }

  /**
    * JDBC draft specification method for setting auto-commit.  Since
    * mSQL has no transaction management, this connection object acts
    * exactly as if auto-commit were set.  So this method does nothing.
    * &see java.sql.Connection#setAutoCommit
    * &param b this does nothing
    */
   public void setAutoCommit(boolean b) throws SQLException {
    // _hb_ to be done soon
  }

  /**
    * Get the current auto-commit state.
    * &return current state of auto-commit mode
    * &see #setAutoCommit
    */
   public boolean getAutoCommit() throws SQLException {
    // _hb_ to be done soon, default is auto-commit
     return true;
  }

  /**
    * JDBC draft specification method for committing a transaction.  Since
    * mSQL has no support for commits or rollbacks, this method does
    * nothing.
    * NOTE: Should I throw an exception here?
    * &see java.sql.Connection#commit
    */
   public void commit() throws SQLException {
    // _hb_ to be done soon
  }

  /**
    * JDBC draft specification method for rolling back a transaction.
    * Since mSQL has no support for rollbacks, this method throws an
    * exception.
    * &see java.sql.Connection#rollback
    * &exception SQLException gets thrown if this ever gets called
    */
   public void rollback() throws SQLException {
    // _hb_ to be done soon
     throw new SQLException("Exception: Rollbacks are not yet
          supported.");
  }

  /**
    * JDBC draft specification method for closing the database connection.
    * &see java.sql.Connection#close
    * &exception SQLException thrown in the event of an MsqlException
    */
   public void close() throws SQLException {
      db2CLI.closeConnection();
      db2CLI.freeEnv();
     db2CLI = null;
  }

  /**
    * JDBC draft specification method for letting others know the
    * connection status.
    * &see java.sql.Connection#isClosed
    * &exception SQLException who knows why Sun thought this needed an
    * exception
    * &return true if the connection is closed, false otherwise
    */
   public boolean isClosed() throws SQLException {
     return (db2CLI == null);
  }

  /**
    * JDBC draft specification method to return information about
    * the database.
    * &see java.sql.Connection#getMetData
    * &exception SQLException thrown if an error occurs reading meta-data
    * &return a DatabaseMetaData object with database info
    */
  public DatabaseMetaData getMetaData()
       throws SQLException {
    return new DB2DatabaseMetaData(db2CLI);
  }

  /**
    * JDBC draft specification method to put the connection in read-only
    * mode. mSQL does not support read-only mode, so this method does
    * nothing.
    * NOTE: Should an exceptionbe thrown here?
    * &see java.sql.Connection#setReadOnly
    * &param b dummy parameter than has no meaning to mSQL
    */
   public void setReadOnly(boolean b) throws SQLException {
  }

  /**
    * JDBC draft specification method to return the read-only status of
    * the connection.  Since mSQL has no such status, this always returns
    * false.
    * &see java.sql.Connection#isReadOnly
    * &return always false
    */
  public boolean isReadOnly() throws SQLException {
    return false;
  }

  /**
    * JDBC draft specification method to select a sub-space of the target
    * database.  It basically has no meaning to mSQL.
    * &see java.sql.Connection#setCatalog
    * &param str the catalog
    */
   public void setCatalog(String str) throws SQLException {
     throw new SQLException("DB2Connection.setCatalog() cannot be used.");
  }

  /**
    * JDBC draft specification method to return the catalog.  This has no
    * meaning to mSQL.
    * &see java.sql.Connection#getCatalog
    * &return the catalog name
    */
   public String getCatalog() throws SQLException {
     return catalog;
  }

  /**
    * JDBC draft specification method for setting the transaction
    * isolation level for the connection.  This has no meaning to mSQL.
    * &see java.sql.Connection#setTransactionIsolation
    * &param x the isolation level
    */
   public void setTransactionIsolation(int x)
        throws SQLException {
     isolation = x;
  }

  /**
    * JDBC draft specification method for retrieving the transaction
    * isolation level for the connection.  This information has no meaning
    * to mSQL.
    * &see java.sql.Connection#getTransactionIsolation
    * &return the transaction isolation level
    */
   public int getTransactionIsolation() throws SQLException {
     return isolation;
  }

  /**
    * When a Connection is in auto-close mode, all its
    * PreparedStatements, CallableStatements, and ResultSets will be
    * closed when a transaction is committed or rolled back.  By
    * default, a new Connection is in auto-close mode.
    *
    * <P> When auto-close is disabled, JDBC attempts to keep
    * all statements and ResultSets open across commits and
    * rollbacks.  However, the actual behaviour will vary depending
    * on what the underlying database supports.  Some databases
    * allow these objects to remain open across commits, whereas
    * other databases insist on closing them.
    *
    * &param autoClose true enables auto-close, false disables
    * auto-close
    *
    * &see DatabaseMetaData#supportsOpenCursorsAcrossCommit
    * &see DatabaseMetaData#supportsOpenCursorsAcrossRollback
    * &see DatabaseMetaData#supportsOpenStatementsAcrossCommit
    * &see DatabaseMetaData#supportsOpenStatementsAcrossRollback
    */
   public void setAutoClose(boolean autoClose) throws SQLException {
     throw new SQLException("DB2Connection.setAutoClose is not yet
         supported.");
  }

  /**
    * Get the current auto-close state.
    * &return current state of auto-close mode
    * &see #setAutoClose
    */
   public boolean getAutoClose() throws SQLException {
     throw new SQLException("DB2Connection.getAutoClose is not yet
         supported.");
  }

  /**
    * JDBC draft specification method for retrieving a chain of warnings
    * related to the connection.
    * &see java.sql.Connection#getWarnings
    * &return the chain of warnings for this connection
    */
   public SQLWarning getWarnings() throws SQLException {
     return null;
  }

  /**
    * JDBC draft specification method for clearing the warning chain.
    * &see java.sql.Connection#clearWarnings
    */
   public void clearWarnings() throws SQLException {
  }

  /**
    * Executes an SQL statement.
    * &param sql the statement to be executed
    * &return nr of rows
    */
   public DB2CLI db2ExecSQL(String sql) throws SQLException {
   try {
       db2CLI.SQLExecQuery(sql);
       return db2CLI;
  }
   catch( DB2CLIException e ) {
       throw new SQLException("DB2CLI exception: " + e.getMessage());
   }
  }

  /**
    * Executes an mSQL statement.
    * &param sql the statement to be executed
    * &return MsqlResult with the results of the statement
    */

  /* _hb_
  public MsqlResult executeMsql(String sql)
       throws SQLException {
   MsqlResult result;

   try {
       result = iMsql.Query(sql);
  }
   catch( DB2CLIException e ) {
       throw new SQLException("mSQL exception: " + e.getMessage());
  }
    return result;
}
*/

  /**
    * Gives the URL used to connect to the database.
    * &return the URL
    */
  // _hb_    public final String getURL() {
  // _hb_    return url;
  // _hb_  }
}

Listing C.3 DB2ResultSet.java.

/*    db2jdbc.sql.DB2ResultSet
 *
 *    Copyright (c) 1996 Heiner Braun
 *    Based on mSQL stuff by George Reese (borg&imaginary.com).
 *    Left original comments; my comments are marked with _hb_.
 *    DB2 implementation of the JDBC draft protocol ResultSet interface.
 */

package  db2jdbc.sql;

import   java.sql.Date;
import   java.sql.Numeric;
import   java.sql.ResultSet;
import   java.sql.ResultSetMetaData;
import   java.sql.SQLException;
import   java.sql.SQLWarning;
import   java.sql.Time;
import   java.sql.Timestamp;
import   java.sql.Types;
import   java.util.Hashtable;
import   db2jdbc.sql.DB2ResultSetMetaData;
import   db2jdbc.sql.db2access.DB2CLI;
import   db2jdbc.sql.db2access.DB2CLIException;

public class DB2ResultSet implements java.sql.ResultSet {
  /**
    * Previous get returned null?
    */
   private boolean wasNull = true;
  /**
    * DB2CLI object
    */
   private DB2CLI db2CLI;
  /**
    * Darryl Collins' MsqlResult object for this query
    */
    //private MsqlResult result;
  /**
    * The current row data
    */
    //private String current_row[];
  /**
    * Field information for the current row
    */
    //MsqlFieldDesc current_fields[];
   /* Row number tracking removed in Imaginary 0.92 */
  /**
    * The meta data for this result set
    */
  private DB2ResultSetMetaData meta;
  /**
    * A Hashtable that maps column names to columns
    */
  private Hashtable column_map = null;
  /**
    * Constructs a new result set object given the MsqlResult specified.
    * &param res the MsqlResult returned from a previously executed query
    */
  public DB2ResultSet(DB2CLI newDB2CLI) {
    db2CLI = newDB2CLI;
  }

  /**
    * JDBC draft specification method for moving the current row to the
    * next row, returning true if there is another row for processing.
    * &see java.sql.ResultSet#next
    * &exception SQLException thrown if an error occurs during processing
    * &return true if there are more rows to process, otherwise false
    */
   public boolean next() throws SQLException {

    // close open input streams from  previous fetch

    try {
      return db2CLI.SQLFetch();
    }
    catch( DB2CLIException e ) {
      throw new SQLException("DB2CLI exception: " + e.getMessage());
    }
  }

  /**
    * JDBC draft specification method for closing a result set.
    * This has no meaning to mSQL.
    * &see java.sql.ResultSet#close
    */
  public void close() throws SQLException {
  }

  /**
    * JDBC specification method to determine if a column is null.
    * &see java.sql.ResultSet#wasNull
    * &exception SQLException in the event of an MsqlException
    * &return true if the column is null, false otherwise
    */
   public boolean wasNull() throws SQLException {
     return wasNull;
  }

  /**
    * JDBC draft specification method for getting a char value from
    * the named column.  Note that the JDBC draft provides that this
    * method gets the value as a char, so you can retrieve int values
    * into String objects.
    * &see java.sql.ResultSet#getChar
    * &exception SQLException thrown for invalid columns or bad rows
    * &param column the column being retrieved
    * &return the column as a String
    */
   public String getString(int column) throws SQLException {
     String ret = null;

    try {
      ret = db2CLI.getString(column);
      wasNull = (ret == null);
      return ret;
    }
    catch( DB2CLIException e ) {
      throw new SQLException("DB2CLI exception: " + e.getMessage());
    }
  }

  /**
    * JDBC specification method for retrieving a column as a boolean
    * value.  Interprets "", null, and "0" as false, others as true.
    * &see java.sql.ResultSet#getBoolean
    * &exception SQLException a sure sign of the apocolypse
    * &param column the column for which the value is being retrieved
    * &return false for "", null, or "0"; true otherwise
    */
  public boolean getBoolean(int column) throws SQLException {
    String bool;
    try {
      bool = db2CLI.getString(column);
    }
    catch( DB2CLIException e ) {
      throw new SQLException("DB2CLI exception: " + e.getMessage());
    }
      if (bool.equals("") || bool == null || bool.equals("0"))
        return false;
    else
      return true;
  }

  /**
    * JDBC draft specification method to retrieve a byte value from
    * the database.
    * &see java.sql.ResultSet#getByte
    * &exception SQLException things did not go so hot
    * &param column the column being retrieved
    * &return the named column as a byte
    */
   public byte getByte(int column) throws SQLException {
     String str;

    if( (str = getString(column)) == null || str.length() == 0 ) return
       (byte)0;
    else if( str.length() != 1 ) {
      throw new SQLException("Data format error: cannot convert string to
         byte.");
    }
    else return (byte)str.charAt(0);

  }

  /**
    * JDBC draft specification method to retrieve a byte value from
    * the database.
    * &see java.sql.ResultSet#getTinyInt
    * &exception SQLException things did not go so hot
    * &param column the column being retrieved
    * &return the named column as a byte
    */
  public short getShort(int column) throws SQLException {
    try {
      return (short)Integer.parseInt(db2CLI.getString(column));
    }
    catch( DB2CLIException e ) {
      throw new SQLException("DB2CLI exception: " + e.getMessage());
    }
  }

  /**
    * JDBC draft specification method to retrieve a short value from
    * the database.
    * &see java.sql.ResultSet#getSmallInt
    * &exception SQLException things did not go so hot
    * &param column the column being retrieved
    * &return the named column as a short
    */
  public int getInt(int column) throws SQLException {
    try {
      return Integer.parseInt(db2CLI.getString(column));
    }
    catch( DB2CLIException e ) {
      throw new SQLException("DB2CLI exception: " + e.getMessage());
    }
  }

  /**
    * JDBC draft specification method to retrieve an integer value from
    * the database.
    * &see java.sql.ResultSet#getInteger
    * &exception SQLException things did not go so hot
    * &param column the column being retrieved
    * &return the named column as an integer
    */
  public long getLong(int column) throws SQLException {
    try {
      return Long.parseLong(db2CLI.getString(column));
    }
    catch( DB2CLIException e ) {
      throw new SQLException("DB2CLI exception: " + e.getMessage());
    }
  }

  /**
    * JDBC draft specification method to retrieve a float value from
    * the database.
    * &see java.sql.ResultSet#getFloat
    * &exception SQLException things did not go so hot
    * &param column the column being retrieved
    * &return the named column as a float
    */
   public float getFloat(int column) throws SQLException {
     Float ret;
    try {
      ret = new Float(db2CLI.getString(column));
    }
    catch( DB2CLIException e ) {
      throw new SQLException("DB2CLI exception: " + e.getMessage());
    }

    return ret.floatValue();
  }

  /**
    * JDBC draft specification method to retrieve a double value from
    * the database.
    * &see java.sql.ResultSet#getDouble
    * &exception SQLException things did not go so hot
    * &param column the column being retrieved
    * &return the named column as a double
    */
  public double getDouble(int column) throws SQLException {
    Double ret;

    try {
      ret = new Double(db2CLI.getString(column));
    }
    catch( DB2CLIException e ) {
      throw new SQLException("DB2CLI exception: " + e.getMessage());
    }

    return ret.doubleValue();
  }

  /**
    * JDBC draft specification method to retrieve a Numeric object from
    * the database.
    * &see java.sql.ResultSet#getNumeric
    * &exception SQLException things did not go so hot
    * &param column the column being retrieved
    * &param scale how many decimal digits after the floating point to
    * maintain
    * &return the named column as a Numeric
    */
   public Numeric getNumeric(int column, int scale)
       throws SQLException {
    try {
       return new Numeric(db2CLI.getString(column));
    }
    catch( DB2CLIException e ) {
      throw new SQLException("DB2CLI exception: " + e.getMessage());
    }
  }

  /**
    * JDBC draft specification method to return a byte array.
    * &see java.sql.ResultSet#getBinary
    * &exception SQLException thrown if something goes wrong
    * &param column the column being retrieved
    * &return a byte array that is the value of the column
    */
  public byte[] getBytes(int column) throws SQLException {
    String str;
    byte b[];

    str = getString(column);
    if( str == null ) return null;
    b = new byte[str.length() + 10];
      str.getBytes(0, str.length(), b, 0);
    return b;
  }

  /**
    * JDBC draft specification for retrieving a date column.
    * Can you say namespace pollution?  I knew you could.
    * &see java.sqlResultSet#getDate
    * @exception SQLException thrown in the event of problems
    * &param column the column being retrieved
    * &return the date value for the column
    */
  public Date getDate(int column)
       throws SQLException {
    try {
      return Date.valueOf(db2CLI.getString(column));
    }
    catch( DB2CLIException e ) {
      throw new SQLException("DB2CLI exception: " + e.getMessage());
    }
  }

  /**
    * JDBC draft specification method for retrieving a time from the
    * database.
    * &see java.sql.ResultSet#getTime
    * &exception SQLException thrown in the event of troubles
    * &param column the column being retrieved
    * &return the column as a java.sql.Time object
    */
  public Time getTime(int column)
       throws SQLException {
    try {
      return Time.valueOf(db2CLI.getString(column));
    }
    catch( DB2CLIException e ) {
      throw new SQLException("DB2CLI exception: " + e.getMessage());
    }
  }

  /**
    * JDBC draft specification method for retrieving a timestamp from
    * the database.
    * &see java.sql.ResultSet#getTimestamp
    * &exception SQLException thrown in the event of troubles
    * &param column the column being retrieved
    * &return the column as a java.sql.Timestamp object
    */
  public Timestamp getTimestamp(int column)
       throws SQLException {
    try {
      return Timestamp.valueOf(db2CLI.getString(column));
    }
    catch( DB2CLIException e ) {
      throw new SQLException("DB2CLI exception: " + e.getMessage());
    }
  }

  /**
    * This is not currently supported.
    * _hb_ necessary for retrieving (HTML-)files?
    */
  public java.io.InputStream getAsciiStream(int column) {
      return null;
  }

  /**
    * This is not currently supported
    */
  public java.io.InputStream getUnicodeStream(int column)
       throws SQLException {
    return null;
  }

  /**
    * This is not currently supported
    */
  public java.io.InputStream getBinaryStream(int column)
       throws SQLException {
    return null;
  }

  //===============================================================
  // Methods for accessing results by column name
  //===============================================================

  /**
    * Get the value of a column in the current row as a Java String.
    *
    * &param columnName is the SQL name of the column
    * &return the column value; if the value is SQL NULL the result is
    * null
    */
  public String getString(String columnName) throws SQLException {
    return getString(findColumn(columnName));
  }

  /**
    * Get the value of a column in the current row as a Java boolean.
    *
    * &param columnName is the SQL name of the column
    * &return the column value; if the value is SQL NULL the result is
    * false
    */
  public boolean getBoolean(String columnName) throws SQLException{
    return getBoolean(findColumn(columnName));
  }

  /**
    * Get the value of a column in the current row as a Java byte.
    *
    * &param columnName is the SQL name of the column
    * &return the column value; if the value is SQL NULL the result is 0
    */
  public byte getByte(String columnName) throws SQLException{
    return getByte(findColumn(columnName));
  }

  /**
    * Get the value of a column in the current row as a Java short.
    *
    * &param columnName is the SQL name of the column
    * &return the column value; if the value is SQL NULL the result is 0
    */
  public short getShort(String columnName) throws SQLException{
    return getShort(findColumn(columnName));
  }

  /**
    * Get the value of a column in the current row as a Java int.
    *
    * &param columnName is the SQL name of the column
    * &return the column value; if the value is SQL NULL the result is 0
    */
  public int getInt(String columnName) throws SQLException{
    return getInt(findColumn(columnName));
  }

  /**
    * Get the value of a column in the current row as a Java long.
    *
    * &param columnName is the SQL name of the column
    * &return the column value; if the value is SQL NULL the result is 0
    */
  public long getLong(String columnName) throws SQLException{
    return getLong(findColumn(columnName));
  }

  /**
    * Get the value of a column in the current row as a Java float.
    *
    * &param columnName is the SQL name of the column
    * &return the column value; if the value is SQL NULL the result is 0
    */
  public float getFloat(String columnName) throws SQLException{
    return getFloat(findColumn(columnName));
  }

  /**
    * Get the value of a column in the current row as a Java double.
    *
    * &param columnName is the SQL name of the column
    * &return the column value; if the value is SQL NULL the result is 0
    */
  public double getDouble(String columnName) throws SQLException{
    return getDouble(findColumn(columnName));
  }

  /**
    * Get the value of a column in the current row as a java.sql.Numeric
    * object.
    *
    * &param columnName is the SQL name of the column
    * &param scale the number of digits to the right of the decimal
    * &return the column value; if the value is SQL NULL the result is
    * null
    */
  public Numeric getNumeric(String columnName, int scale) throws
    SQLException{
      return getNumeric(findColumn(columnName), scale);
  }

  /**
    * Get the value of a column in the current row as a Java byte array.
    * The bytes represent the raw values returned by the driver.
    *
    * &param columnName is the SQL name of the column
    * &return the column value; if the value is SQL NULL the result is
    * null
    */
  public byte[] getBytes(String columnName) throws SQLException{
    return getBytes(findColumn(columnName));
  }

  /**
    * Get the value of a column in the current row as a java.sql.Date
    * object.
    *
    * &param columnName is the SQL name of the column
    * &return the column value; if the value is SQL NULL the result is
    * null
    */
  public java.sql.Date getDate(String columnName) throws SQLException{
    return getDate(findColumn(columnName));
  }

  /**
    * Get the value of a column in the current row as a java.sql.Time
    * object.
    *
    * &param columnName is the SQL name of the column
    * &return the column value; if the value is SQL NULL the result is
    * null
    */
  public java.sql.Time getTime(String columnName) throws SQLException{
    return getTime(findColumn(columnName));
  }

  /**
    * Get the value of a column in the current row as a java.sql.Timestamp
    * object.
    *
    * &param columnName is the SQL name of the column
    * &return the column value; if the value is SQL NULL the result is
    * null
    */
  public java.sql.Timestamp getTimestamp(String columnName) throws
    SQLException {
      return getTimestamp(findColumn(columnName));
  }

  /**
    * A column value can be retrieved as a stream of ASCII characters
    * and then read in chunks from the stream.  This method is
    * particularly suitable for retrieving large LONGVARCHAR values.  The
    * JDBC driver will do any necessary conversion from the database
    * format into ASCII.
    *
    * <P><B>Note:</B> All the data in the returned stream must
    * be read prior to getting the value of any other column. The
    * next call to a get method implicitly closes the stream.
    *
    * &param columnName is the SQL name of the column
    * &return a Java input stream that delivers the database column value
    * as a stream of one byte ASCII characters; if the value is SQL NULL
    * then the result is null
    */
  public java.io.InputStream getAsciiStream(String columnName) throws
    SQLException {
      return getAsciiStream(findColumn(columnName));
  }

  /**
    * A column value can be retrieved as a stream of Unicode characters
    * and then read in chunks from the stream.  This method is
    * particularly suitable for retrieving large LONGVARCHAR values.  The
    * JDBC driver will do any necessary conversion from the database
    * format into Unicode.
    *
    * <P><B>Note:</B> All the data in the returned stream must
    * be read prior to getting the value of any other column. The
    * next call to a get method implicitly closes the stream.
    *
    * &param columnName is the SQL name of the column
    * &return a Java input stream that delivers the database column value
    * as a stream of two byte Unicode characters; if the value is SQL
    * NULL then the result is null
    */
  public java.io.InputStream getUnicodeStream(String columnName) throws
    SQLException {
      return getUnicodeStream(findColumn(columnName));
  }

  /**
    * A column value can be retrieved as a stream of uninterpreted bytes
    * and then read in chunks from the stream.  This method is
    * particularly suitable for retrieving large LONGVARBINARY values.
    *
    * <P><B>Note:</B> All the data in the returned stream must
    * be read prior to getting the value of any other column. The
    * next call to a get method implicitly closes the stream.
    *
    * &param columnName is the SQL name of the column
    * &return a Java input stream that delivers the database column value
    * as a stream of uninterpreted bytes; if the value is SQL NULL
    * then the result is null
    */
  public java.io.InputStream getBinaryStream(String columnName)
    throws SQLException{
    return getBinaryStream(findColumn(columnName));
  }

  //===============================================================
  // Advanced features
  //===============================================================

  /**
    * JDBC draft specification for getting the chain of warnings for this
    * statement.
    * &see java.sql.Statement#getWarnings
    * &return the chain of warnings
    */
  public SQLWarning getWarnings() throws SQLException {
    return null;
  }

  /**
    * JDBC draft specification for clearing the warning chain.
    * &see java.sql.Statement#clearWarnings
    */
  public void clearWarnings() throws SQLException {
  }

  /**
    * JDBC draft specification method for returning a cursor name.
    * mSQL does not support this feature.
    * &see java.sql.ResultSet#getCursorName
    * &return ""
    */
  public String getCursorName() throws SQLException {
    throw new SQLException("Cursors are not yet supported.");
  }

  /**
    * JDBC draft specification method for returning meta-deta on a result
    * set.
    * &see java.sql.ResultSet#getMetaData
    * &exception SQLException thrown on error getting meta-data
    * &return ResultSetMetaData object containing result set info
    */
  public ResultSetMetaData getMetaData()
       throws SQLException {
    if( meta == null ) {
      meta = new DB2ResultSetMetaData(db2CLI);
    }
    return meta;
  }

  /**
    * <p>Get the value of a column as a Java object.
    *
    * <p>This method will convert the result column to the specified SQL
    * type and then return a Java object corresponding to the specified
    * SQL type.
    *
    * <p>Note that this method may be used to read datatabase specific
    * abstract data types by specifying a targetSqlType of
    * java.sql.types.OTHER, which allows the driver to return a database
    * specific Java type.
    *
    * &param columnIndex the first column is 1, the second is 2, ...
    * &param targetSqlType this should specify the desired type for the
    * result  as a java.sql.Type; the scale argument may further
    * qualify this type
    * &param scale for java.sql.Types.DECIMAL or java.sql.Types.NUMERIC
    * types; this is the number of digits after the decimal; for
    * all other types, this value will be ignored
    * &return a java.lang.Object holding the column value
    * &see Types
    */
  public Object getObject(int column, int type, int scale)
    throws SQLException {
     switch(type) {
     case Types.BIT:
       return new Boolean(getBoolean(column));

     case Types.TINYINT:
       return new Character((char)getByte(column));

     case Types.SMALLINT:
       return new Integer(getInt(column));

     case Types.INTEGER:
       return new Integer(getInt(column));

     case Types.BIGINT:
       return new Long(getLong(column));

     case Types.FLOAT:
       return new Float(getFloat(column));

     case Types.REAL:
       return new Float(getFloat(column));

     case Types.DOUBLE:
       return new Double(getDouble(column));

     case Types.NUMERIC:
       return getNumeric(column, scale);

     case Types.DECIMAL:
       return getNumeric(column, scale);

     case Types.CHAR:
       return getString(column);

     case Types.VARCHAR:
       return getString(column);

     case Types.LONGVARCHAR:
       return getString(column);

     case Types.DATE:
       return getDate(column);

     case Types.TIME:
       return getTime(column);

     case Types.TIMESTAMP:
       return getTimestamp(column);

     case Types.BINARY:
       // _hb_ is this an object?
       // _hb_ maybe use a Vector of Character? fill
       return getBytes(column);

     case Types.VARBINARY:
       return getBytes(column);

     case Types.LONGVARBINARY:
       return getBytes(column);

     default:
       return null;
    }
  }

  /**
    * This method is like getObject above but assumes scale of zero.
    */
  public Object getObject(int columnIndex, int targetSqlType) throws
    SQLException{
      return getObject(columnIndex, targetSqlType, 0);
  }

  /**
    * <p>Get the value of a column as a Java object.
    *
    * <p>This method will return the value of the given column as a Java
    * object.  The type of the Java object will be default Java Object
    * type corresponding to the column's SQL type, following the mapping
    * specified in the JDBC spec.
    *
    * <p>This method may also be used to read datatabase specific abstract
    * data types.
    *
    * &param columnIndex the first column is 1, the second is 2, ...
    * &return a java.lang.Object holding the column value
    */
  public Object getObject(int columnIndex) throws SQLException {
    return getObject(columnIndex, getMetaData().
    getColumnType(columnIndex));
  }
  //===============================================================
  // Now three similar getObject methods using column names
  //===============================================================

  public Object getObject(String columnName, int targetSqlType, int
    scale) throws SQLException{
      return getObject(findColumn(columnName), targetSqlType, scale);
  }

  public Object getObject(String columnName, int targetSqlType) throws
    SQLException{
      return getObject(findColumn(columnName), targetSqlType, 0);
  }

  public Object getObject(String columnName) throws SQLException{
    return getObject(findColumn(columnName));
  }

  /**
    * Given a column name, this method returns the column number for that
    * name.  Column name to number mappings are kept inside a Hashtable.
    * Applications that do not need the overhead of this calculation are
    * not penalized since the mapping only occurs on the first attempt to
    * access a column number by name.
    * &exception java.sql.SQLException thrown if a bad name is passed
    * &param name the name of the column desired
    * &return the column number, 1 being the first column
    */
  public int findColumn(String name) throws SQLException {
    Integer num;

    if( column_map == null ) {
      ResultSetMetaData m;
        int i, maxi;

      m = getMetaData();
      column_map = new Hashtable(maxi = m.getColumnCount());
        for(i=0; i<maxi; i++) {
             // for testing:
             // System.out.println("Column " + (i + 1) + " : <" +
            // m.getColumnName(i + 1) + ">");

             column_map.put(m.getColumnName(i + 1), new Integer(i+1));
      }
    }
    // _hb_ column names are case insensitive --> considered?
    num = (Integer)column_map.get(name);
    if( num == null ) {
      throw new SQLException("Invalid column name: " + name);
    }
      return num.intValue();
  }
}

Listing C.4 DB2ResultSetMetaData.java.

/*    db2jdbc.sql.DB2DatabaseMetaData
 *
 *    Copyright (c) 1996 Heiner Braun
 *    Based on DatabaseMetaData interface code from Sun.
 *    Left original comments, except for some very long elaborations...
 *    DB2 implementation of the JDBC DatabaseMetaData interface.
 *    This provides just a frame to start. Nearly nothing is done.
 */
// This class provides information about the database as a whole.
//
// Many of the methods here return lists of information in ResultSets.
// You can use the normal ResultSet methods such as getString and getInt
// to retrieve the data from these ResultSets.  If a given form of
// metadata is not available, these methods show throw a SQLException.
//
// Some of these methods take arguments that are String patterns.  These
// methods all have names such as fooPattern.  Within a pattern String
// "%" means match any substring of 0 or more characters and "_" means
// match any one character.
//

package db2jdbc.sql;

import java.sql.*;
import db2jdbc.sql.db2access.DB2CLI;

public class DB2DatabaseMetaData implements java.sql.DatabaseMetaData {

  /**
    * DB2CLI object
    */
  private DB2CLI db2CLI = null;

  /**
    * Constructs a new JDBC specification DatabaseMetaData object for the
    * local DB2 database.
    */
  public DB2DatabaseMetaData(DB2CLI newdb2CLI) throws SQLException {
    db2CLI = newdb2CLI;
  }

//---------------------------------------------------------------------
  // First, a variety of minor information about the target database.

  /**
    * Can all the procedures returned by getProcedures be called by the
    * current user?
    *
    * &return true if so
    */
  public boolean allProceduresAreCallable() throws SQLException {
    throw new SQLException("DB2DatabaseMetaData. allProcedures
      AreCallable() " + "is not yet implemented.");
  }

  /**
    * Can all the tables returned by getTable be SELECTed by the
    * current user?
    *
    * &return true if so
    */
  public boolean allTablesAreSelectable() throws SQLException {
    throw new SQLException("DB2DatabaseMetaData.allTablesAreSelectable()
            " + "is not yet implemented.");
  }

  /**
    * What's the url for this database?
    *
    * &return the url or null if it can't be generated
    */
  public String getURL() throws SQLException {
    throw new SQLException("DB2DatabaseMetaData.getURL() " +
            " is not yet implemented.");
  }

  /**
    * What's our user name as known to the database?
    *
    * &return our database user name
    */
  public String getUserName() throws SQLException {
    throw new SQLException("DB2DatabaseMetaData.getUserName() " +
            "is not yet implemented.");
  }

  /**
    * Is the database in read-only mode?
    *
    * &return true if so
    */
  public boolean isReadOnly() throws SQLException {
    throw new SQLException("DB2DatabaseMetaData.isReadOnly() " +
            "is not yet implemented.");
  }

  /**
    * Are NULL values sorted high?
    *
    * &return true if so
    */
  public boolean nullsAreSortedHigh() throws SQLException {
    throw new SQLException("DB2DatabaseMetaData.nullsAreSortedHigh() " +
            "is not yet implemented.");
  }

  /**
    * Are NULL values sorted low?
    *
    * &return true if so
    */
  public boolean nullsAreSortedLow() throws SQLException {
    throw new SQLException("DB2DatabaseMetaData.nullsAreSortedLow() " +
            "is not yet implemented.");
  }

  /**
    * Are NULL values sorted at the start regardless of sort order?
    *
    * &return true if so
    */
  public boolean nullsAreSortedAtStart() throws SQLException {
    throw new SQLException("DB2DatabaseMetaData.nullsAreSortedAtStart() "
            + "is not yet implemented.");
  }

  /**
    * Are NULL values sorted at the end regardless of sort order?
    *
    * &return true if so
    */
  public boolean nullsAreSortedAtEnd() throws SQLException {
    throw new SQLException("DB2DatabaseMetaData.nullsAreSortedAtEnd() " +
            "is not yet implemented.");
  }

  /**
    * What's the name of this database product?
    *
    * &return database product name
    */
  public String getDatabaseProductName() throws SQLException {
    throw new SQLException("DB2DatabaseMetaData.getDatabaseProductName()
            " + "is not yet implemented.");
  }

  /**
    * What's the version of this database product?
    *
    * &return database version
    */
  public String getDatabaseProductVersion() throws SQLException {
    throw new SQLException("DB2DatabaseMetaData. getDatabase
    ProductVersion() " + "is not yet implemented.");
  }

  /**
    * What's the name of this JDBC driver?
    *
    * &return JDBC driver name
    */
  public String getDriverName() throws SQLException {
    return "Local DB2 JDBC prototype driver";
  }

  /**
    * What's the version of this JDBC driver?
    *
    * &return JDBC driver version
    */
  public String getDriverVersion() throws SQLException {
    return "0.1 alpha";
  }

  /**
    * What's this JDBC driver's major version number?
    *
    * &return JDBC driver major version
    */
  public int getDriverMajorVersion() {
    return 0;
  }

  /**
    * What's this JDBC driver's minor version number?
    *
    * &return JDBC driver minor version number
    */
  public int getDriverMinorVersion(){
    return 1;
  }

  /**
    * Does the database store tables in a local file?
    *
    * &return true if so
    */
  public boolean usesLocalFiles() throws SQLException {
    throw new SQLException("DB2DatabaseMetaData.usesLocalFiles() " +
            "is not yet implemented.");
  }

  /**
    * Does the database use a file for each table?
    *
    * &return true if the database uses a local file for each table
    */
  public boolean usesLocalFilePerTable() throws SQLException {
    throw new SQLException("DB2DatabaseMetaData.usesLocalFilePerTable() "
           + "is not yet implemented.");
  }

  /**
    * Does the database support mixed case unquoted SQL identifiers?
    *
    * &return true if so
    */
  public boolean supportsMixedCaseIdentifiers() throws SQLException {
    throw new SQLException("DB2DatabaseMetaData.
    supportsMixedCaseIdentifiers() " + "is not yet implemented.");
  }

  /**
    * Does the database store mixed case unquoted SQL identifiers in
    * upper case?
    *
    * &return true if so
    */
  public boolean storesUpperCaseIdentifiers() throws SQLException {
    throw new SQLException("DB2DatabaseMetaData. storesUpperCase
    Identifiers() " + "is not yet implemented.");
  }

  /**
    * Does the database store mixed case unquoted SQL identifiers in
    * lower case?
    *
    * &return true if so
    */
  public boolean storesLowerCaseIdentifiers() throws SQLException {
    throw new SQLException("DB2DatabaseMetaData. storesLowerCase
    Identifiers() " + "is not yet implemented.");
  }

  /**
    * Does the database store mixed case unquoted SQL identifiers in
    * mixed case?
    *
    * &return true if so
    */
  public boolean storesMixedCaseIdentifiers() throws SQLException {
    throw new SQLException("DB2DatabaseMetaData. storesMixedCase
    Identifiers() " + "is not yet implemented.");
  }

  /**
    * Does the database support mixed case quoted SQL identifiers?
    *
    * A JDBC compliant driver will always return true.
    *
    * &return true if so
    */
  public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException {
    throw new SQLException("DB2DatabaseMetaData.
    supportsMixedCaseQuotedIdentifiers() " + "is not yet implemented.");
  }

  /**
    * Does the database store mixed case quoted SQL identifiers in
    * upper case?
    *
    * A JDBC compliant driver will always return true.
    *
    * &return true if so
    */
  public boolean storesUpperCaseQuotedIdentifiers() throws SQLException {
    throw new SQLException("DB2DatabaseMetaData. storesUpperCase
    QuotedIdentifiers() " + "is not yet implemented.");
  }

  /**
    * Does the database store mixed case quoted SQL identifiers in
    * lower case?
    *
    * A JDBC compliant driver will always return false.
    *
    * &return true if so
    */
  public boolean storesLowerCaseQuotedIdentifiers() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
            "are not yet implemented.");
  }

  /**
    * Does the database store mixed case quoted SQL identifiers in
    * mixed case?
    *
    * A JDBC compliant driver will always return false.
    *
    * &return true if so
    */
  public boolean storesMixedCaseQuotedIdentifiers() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
            "are not yet implemented.");
  }

  /**
    * What's the string used to quote SQL identifiers?
    * This returns a space " " if identifier quoting isn't supported.
    *
    * A JDBC compliant driver always uses a double quote character.
    *
    * &return the quoting string
    */
  public String getIdentifierQuoteString() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
            "are not yet implemented.");
  }

  /**
    * Get a comma separated list of all a database's SQL keywords
    * that are NOT also SQL-92 keywords.
    *
    * &return the list
    */
  public String getSQLKeywords() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
            "are not yet implemented.");
  }

  /**
    * Get a comma separated list of math functions.
    *
    * &return the list
    */
  public String getNumericFunctions() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
            "are not yet implemented.");
  }

  /**
    * Get a comma separated list of string functions.
    *
    * &return the list
    */
  public String getStringFunctions() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
            "are not yet implemented.");
  }

  /**
    * Get a comma separated list of system functions.
    *
    * &return the list
    */
  public String getSystemFunctions() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
            "are not yet implemented.");
  }

  /**
    * Get a comma separated list of time and date functions.
    *
    * &return the list
    */
  public String getTimeDateFunctions() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
            "are not yet implemented.");
  }

  /**
    * This is the string that can be used to escape '_' or '%' in
    * the string pattern style catalog search parameters.
    *
    * <P>The '_' character represents any single character.
    * <P>The '%' character represents any sequence of zero or
    * more characters.
    *
    * &return the string used to escape wildcard characters
    */
  public String getSearchStringEscape() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
            "are not yet implemented.");
  }

  /**
    * Get all the "extra" characters that can be used in unquoted
    * identifier names (those beyond a-z, 0-9 and _).
    *
    * &return the string containing the extra characters
    */
  public String getExtraNameCharacters() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
            "are not yet implemented.");
  }

//---------------------------------------------------------------------
  // Functions describing which features are supported.

  /**
    * Is "ALTER TABLE" with add column supported?
    *
    * &return true if so
    */
  public boolean supportsAlterTableWithAddColumn() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
            "are not yet implemented.");
  }

  /**
    * Is "ALTER TABLE" with drop column supported?
    *
    * &return true if so
    */
  public boolean supportsAlterTableWithDropColumn() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
            "are not yet implemented.");
  }

  /**
    * Is column aliasing supported?
    *
    * <P>If so, the SQL AS clause can be used to provide names for
    * computed columns or to provide alias names for columns as
    * required.
    *
    * A JDBC compliant driver always returns true.
    *
    * &return true if so
    */
  public boolean supportsColumnAliasing() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
            "are not yet implemented.");
  }

  /**
    * Are concatenations between NULL and non-NULL values NULL?
    *
    * A JDBC compliant driver always returns true.
    *
    * &return true if so
    */
  public boolean nullPlusNonNullIsNull() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
            "are not yet implemented.");
  }

  /**
    * Is the CONVERT function between SQL types supported?
    *
    * &return true if so
    */
  public boolean supportsConvert() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
            "are not yet implemented.");
  }

  /**
    * Is CONVERT between the given SQL types supported?
    *
    * &param fromType the type to convert from
    * &param toType the type to convert to
    * &return true if so
    * &see Types
    */
  public boolean supportsConvert(int fromType, int toType) throws
    SQLException { throw new SQLException("Many methods from
            DB2DatabaseMetaData " + "are not yet implemented.");
  }

  /**
    * Are table correlation names supported?
    *
    * A JDBC compliant driver always returns true.
    *
    * &return true if so
    */
  public boolean supportsTableCorrelationNames() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                               "are not yet implemented.");
  }

  /**
    * If table correlation names are supported, are they restricted
    * to be different from the names of the tables?
    *
    * A JDBC compliant driver always returns true.
    *
    * &return true if so
    */
  public boolean supportsDifferentTableCorrelationNames() throws
    SQLException { throw new SQLException("Many methods from
                             DB2DatabaseMetaData " + "are not
                                     yet implemented.");
  }

  /**
    * Are expressions in "ORDER BY" lists supported?
    *
    * &return true if so
    */
  public boolean supportsExpressionsInOrderBy() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                              "are not yet implemented.");
  }

  /**
    * Can an "ORDER BY" clause use columns not in the SELECT?
    *
    * &return true if so
    */
  public boolean supportsOrderByUnrelated() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * Is some form of "GROUP BY" clause supported?
    *
    * &return true if so
    */
  public boolean supportsGroupBy() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                     "are not yet implemented.");
  }

  /**
    * Can a "GROUP BY" clause use columns not in the SELECT?
    *
    * &return true if so
    */
  public boolean supportsGroupByUnrelated() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                    "are not yet implemented.");
  }

  /**
    * Can a "GROUP BY" clause add columns not in the SELECT,
    * provided it specifies all the columns in the SELECT?
    *
    * &return true if so
    */
  public boolean supportsGroupByBeyondSelect() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                 "are not yet implemented.");
  }

  /**
    * Is the escape character in "LIKE" clauses supported?
    *
    * A JDBC compliant driver always returns true.
    *
    * &return true if so
    */
  public boolean supportsLikeEscapeClause() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                     "are not yet implemented.");
  }

  /**
    * Are multiple ResultSets from a single execute supported?
    *
    * &return true if so
    */
  public boolean supportsMultipleResultSets() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                    "are not yet implemented.");
  }

  /**
    * Can we have multiple transactions open at once (on different
    * connections)?
    *
    * &return true if so
    */
  public boolean supportsMultipleTransactions() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                    "are not yet implemented.");
  }

  /**
    * Can columns be defined as non-nullable?
    *
    * A JDBC compliant driver always returns true.
    *
    * &return true if so
    */
  public boolean supportsNonNullableColumns() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                     "are not yet implemented.");
  }

  /**
    * Is the ODBC Minimum SQL grammar supported?
    *
    * All JDBC compliant drivers must return true.
    *
    * &return true if so
    */
  public boolean supportsMinimumSQLGrammar() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                     "are not yet implemented.");
  }

  /**
    * Is the ODBC Core SQL grammar supported?
    *
    * &return true if so
    */
  public boolean supportsCoreSQLGrammar() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                     "are not yet implemented.");
  }

  /**
    * Is the ODBC Extended SQL grammar supported?
    *
    * &return true if so
    */
  public boolean supportsExtendedSQLGrammar() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                    "are not yet implemented.");
  }

  /**
    * Is the ANSI92 entry level SQL grammar supported?
    *
    * All JDBC compliant drivers must return true.
    *
    * &return true if so
    */
  public boolean supportsANSI92EntryLevelSQL() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                     "are not yet implemented.");
  }

  /**
    * Is the ANSI92 intermediate SQL grammar supported?
    *
    * &return true if so
    */
  public boolean supportsANSI92IntermediateSQL() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                     "are not yet implemented.");
  }

  /**
    * Is the ANSI92 full SQL grammar supported?
    *
    * &return true if so
    */
  public boolean supportsANSI92FullSQL() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                     "are not yet implemented.");
  }

  /**
    * Is the SQL Integrity Enhancement Facility supported?
    *
    * &return true if so
    */
  public boolean supportsIntegrityEnhancementFacility() throws
    SQLException {
      throw new SQLException("Many methods from DB2Database
          MetaData " + "are not yet implemented.");
  }

  /**
    * Is some form of outer join supported?
    *
    * &return true if so
    */
  public boolean supportsOuterJoins() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                    "are not yet implemented.");
  }

  /**
    * Are full nested outer joins supported?
    *
    * &return true if so
    */
  public boolean supportsFullOuterJoins() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                     "are not yet implemented.");
  }

  /**
    * Is there limited support for outer joins?  (This will be true
    * if supportFullOuterJoins is true.)
    *
    * &return true if so
    */
  public boolean supportsLimitedOuterJoins() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * What's the database vendor's preferred term for "schema"?
    *
    * &return the vendor term
    */
  public String getSchemaTerm() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                      "are not yet implemented.");
  }

  /**
    * What's the database vendor's preferred term for "procedure"?
    *
    * &return the vendor term
    */
  public String getProcedureTerm() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * What's the database vendor's preferred term for "catalog"?
    *
    * &return the vendor term
    */
  public String getCatalogTerm() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * Does a catalog appear at the start of a qualified table name?
    * (Otherwise it appears at the end.)
    *
    * &return true if it appears at the start
    */
  public boolean isCatalogAtStart() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * What's the separator between catalog and table name?
    *
    * &return the separator string
    */
  public String getCatalogSeparator() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * Can a schema name be used in a data manipulation statement?
    *
    * &return true if so
    */
  public boolean supportsSchemasInDataManipulation() throws SQLException{
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * Can a schema name be used in a procedure call statement?
    *
    * &return true if so
    */
  public boolean supportsSchemasInProcedureCalls() throws SQLException{
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                      "are not yet implemented.");
  }

  /**
    * Can a schema name be used in a table definition statement?
    *
    * &return true if so
    */
  public boolean supportsSch emasInTableDefinitions() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * Can a schema name be used in an index definition statement?
    *
    * &return true if so
    */
  public boolean supportsSchemasInIndexDefinitions() throws SQLException{
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * Can a schema name be used in a privilege definition statement?
    *
    * &return true if so
    */
  public boolean supportsSchemasInPrivilegeDefinitions() throws
    SQLException { throw new SQLException("Many methods
    from DB2DatabaseMetaData " + "are not yet implemented.");
  }

  /**
    * Can a catalog name be used in a data manipulation statement?
    *
    * &return true if so
    */
  public boolean supportsCatalogsInDataManipulation() throws SQLException{
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                      "are not yet implemented.");
  }

  /**
    * Can a catalog name be used in a procedure call statement?
    *
    * &return true if so
    */
  public boolean supportsCatalogsInProcedureCalls() throws SQLException{
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                     "are not yet implemented.");
  }

  /**
    * Can a catalog name be used in a table definition statement?
    *
    * &return true if so
    */
  public boolean supportsCatalogsInTableDefinitions() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                     "are not yet implemented.");
  }

  /**
    * Can a catalog name be used in an index definition statement?
    *
    * &return true if so
    */
  public boolean supportsCatalogsInIndexDefinitions() throws SQLException{
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                     "are not yet implemented.");
  }

  /**
    * Can a catalog name be used in a privilege definition statement?
    *
    * &return true if so
    */
  public boolean supportsCatalogsInPrivilegeDefinitions() throws
    SQLException {
      throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * Is positioned DELETE supported?
    *
    * &return true if so
    */
  public boolean supportsPositionedDelete() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                      "are not yet implemented.");
  }

  /**
    * Is positioned UPDATE supported?
    *
    * &return true if so
    */
  public boolean supportsPositionedUpdate() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                      "are not yet implemented.");
  }

  /**
    * Is SELECT for UPDATE supported?
    *
    * &return true if so
    */
  public boolean supportsSelectForUpdate() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * Are stored procedure calls using the stored procedure escape
    * syntax supported?
    *
    * &return true if so
    */
  public boolean supportsStoredProcedures() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * Are subqueries in comparison expressions supported?
    *
    * A JDBC compliant driver always returns true.
    *
    * &return true if so
    */
  public boolean supportsSubqueriesInComparisons() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                      "are not yet implemented.");
  }

  /**
    * Are subqueries in exists expressions supported?
    *
    * A JDBC compliant driver always returns true.
    *
    * &return true if so
    */
  public boolean supportsSubqueriesInExists() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented."
  }

  /**
    * Are subqueries in "in" statements supported?
    *
    * A JDBC compliant driver always returns true.
    *
    * &return true if so
    */
  public boolean supportsSubqueriesInIns() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * Are subqueries in quantified expressions supported?
    *
    * A JDBC compliant driver always returns true.
    *
    * &return true if so
    */
  public boolean supportsSubqueriesInQuantifieds() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * Are correlated subqueries supported?
    *
    * A JDBC compliant driver always returns true.
    *
    * &return true if so
    */
  public boolean supportsCorrelatedSubqueries() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * Is SQL UNION supported?
    *
    * A JDBC compliant driver always returns true.
    *
    * &return true if so
    */
  public boolean supportsUnion() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                     "are not yet implemented.");
  }

  /**
    * Is SQL UNION ALL supported?
    *
    * A JDBC compliant driver always returns true.
    *
    * &return true if so
    */
  public boolean supportsUnionAll() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                      "are not yet implemented.");
  }

  /**
    * Can cursors remain open across commits?
    *
    * &return true if so
    * &see Connection#disableAutoClose
    */
  public boolean supportsOpenCursorsAcrossCommit() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * Can cursors remain open across rollbacks?
    *
    * &return true if so
    * &see Connection#disableAutoClose
    */
  public boolean supportsOpenCursorsAcrossRollback() throws SQLException{
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * Can statements remain open across commits?
    *
    * &return true if so
    * &see Connection#disableAutoClose
    */
  public boolean supportsOpenStatementsAcrossCommit() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * Can statements remain open across rollbacks?
    *
    * &return true if so
    * &see Connection#disableAutoClose
    */
  public boolean supportsOpenStatementsAcrossRollback() throws
    SQLException {
      throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }
//----------------------------------------------------------------------
  // The following group of methods exposes various limitations
  // based on the target database with the current driver.
  // Unless otherwise specified, a result of zero means there is no
  // limit, or the limit is not known.

  /**
    * How many hex characters can you have in an inline binary literal?
    *
    * &return max literal length
    */
  public int getMaxBinaryLiteralLength() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                      "are not yet implemented.");
  }

  /**
    * What's the max length for a character literal?
    *
    * &return max literal length
    */
  public int getMaxCharLiteralLength() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                      "are not yet implemented.");
  }

  /**
    * What's the limit on column name length?
    *
    * &return max literal length
    */
  public int getMaxColumnNameLength() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                      "are not yet implemented.");
  }

  /**
    * What's the maximum number of columns in a "GROUP BY" clause?
    *
    * &return max number of columns
    */
  public int getMaxColumnsInGroupBy() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                      "are not yet implemented.");
  }

  /**
    * What's the maximum number of columns allowed in an index?
    *
    * &return max columns
    */
  public int getMaxColumnsInIndex() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                      "are not yet implemented.");
  }

  /**
    * What's the maximum number of columns in an "ORDER BY" clause?
    *
    * &return max columns
    */
  public int getMaxColumnsInOrderBy() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                      "are not yet implemented.");
  }

  /**
    * What's the maximum number of columns in a "SELECT" list?
    *
    * &return max columns
    */
  public int getMaxColumnsInSelect() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                     "are not yet implemented.");
  }

  /**
    * What's the maximum number of columns in a table?
    *
    * &return max columns
    */
  public int getMaxColumnsInTable() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                      "are not yet implemented.");
  }

  /**
    * How many active connections can we have at a time to this database?
    *
    * &return max connections
    */
  public int getMaxConnections() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * What's the maximum cursor name length?
    *
    * &return max cursor name length in bytes
    */
  public int getMaxCursorNameLength() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * What's the maximum length of an index (in bytes)?
    *
    * &return max index length in bytes
    */
  public int getMaxIndexLength() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * What's the maximum length allowed for a schema name?
    *
    * &return max name length in bytes
    */
  public int getMaxSchemaNameLength() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * What's the maximum length of a procedure name?
    *
    * &return max name length in bytes
    */
  public int getMaxProcedureNameLength() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * What's the maximum length of a catalog name?
    *
    * &return max name length in bytes
    */
  public int getMaxCatalogNameLength() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * What's the maximum length of a single row?
    *
    * &return max row size in bytes
    */
  public int getMaxRowSize() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * Did getMaxRowSize() include LONGVARCHAR and LONGVARBINARY
    * blobs?
    *
    * &return true if so
    */
  public boolean doesMaxRowSizeIncludeBlobs() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * What's the maximum length of a SQL statement?
    *
    * &return max length in bytes
    */
  public int getMaxStatementLength() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * How many active statements can we have open at one time to this
    * database?
    *
    * &return the maximum
    */
  public int getMaxStatements() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * What's the maximum length of a table name?
    *
    * &return max name length in bytes
    */
  public int getMaxTableNameLength() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * What's the maximum number of tables in a SELECT?
    *
    * &return the maximum
    */
  public int getMaxTablesInSelect() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * What's the maximum length of a user name?
    *
    * &return max name length in bytes
    */
  public int getMaxUserNameLength() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }
//---------------------------------------------------------------------
  /**
    * What's the database's default transaction isolation level?  The
    * values are defined in java.sql.Connection.
    *
    * &return the default isolation level
    * &see Connection
    */
  public int getDefaultTransactionIsolation() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                     "are not yet implemented.");
  }

  /**
    * Are transactions supported? If not, commit is a no-op and the
    * isolation level is TRANSACTION_NONE.
    *
    * &return true if transactions are supported
    */
  public boolean supportsTransactions() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                     "are not yet implemented.");
  }

  /**
    * Does the database support the given transaction isolation level?
    *
    * &param level the values are defined in java.sql.Connection
    * &return true if so
    * &see Connection
    */
  public boolean supportsTransactionIsolationLevel(int level)
                                 throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                      "are not yet implemented.");
  }

  /**
    * Are both data definition and data manipulation statements
    * within a transaction supported?
    *
    * &return true if so
    */
  public boolean supportsDataDefinitionAndDataManipulationTransactions()
                                throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                      "are not yet implemented.");
  }

  /**
    * Are only data manipulation statements within a transaction
    * supported?
    *
    * &return true if so
    */
  public boolean supportsDataManipulationTransactionsOnly()
                                 throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * Does a data definition statement within a transaction force the
    * transaction to commit?
    *
    * &return true if so
    */
  public boolean dataDefinitionCausesTransactionCommit()
                                   throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * Is a data definition statement within a transaction ignored?
    *
    * &return true if so
    */
  public boolean dataDefinitionIgnoredInTransactions()
                                   throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * Get a description of stored procedures available in a
    * catalog.
    *
    * &param catalog a catalog name; "" retrieves those without a catalog
    * &param schemaPattern a schema name pattern; "" retrieves those
    * without a schema
    * &param procedureNamePattern a procedure name pattern
    * &return ResultSet each row is a procedure description
    * &see #getSearchStringEscape
    */
  public ResultSet getProcedures(String catalog, String schemaPattern,
                           String procedureNamePattern) throws
                        SQLException {throw new SQLException("Many
    methods from DB2DatabaseMetaData " + "are not yet implemented.");
  }

  /**
    * Get a description of a catalog's stored procedure parameters
    * and result columns.
    *
    * <P>Only descriptions matching the schema, procedure and
    * parameter name criteria are returned.  They are ordered by
    * PROCEDURE_SCHEM and PROCEDURE_NAME. Within this, the return value,
    * if any, is first. Next are the parameter descriptions in call
    * order. The column descriptions follow in column number order.
    *
    * &param catalog a catalog name; "" retrieves those without a catalog
    * &param schemaPattern a schema name pattern; "" retrieves those
    * without a schema
    * &param procedureNamePattern a procedure name pattern
    * &param columnNamePattern a column name pattern
    * &return ResultSet each row is a stored procedure parameter or
    * column description
    * &see #getSearchStringEscape
    */
  public ResultSet getProcedureColumns(String catalog,
                                String schemaPattern,
                                String procedureNamePattern,
                 String columnNamePattern) throws SQLException {
  throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * Get a description of tables available in a catalog.
    *
    * &param catalog a catalog name; "" retrieves those without a catalog
    * &param schemaPattern a schema name pattern; "" retrieves those
    * without a schema
    * &param tableNamePattern a table name pattern
    * &param types a list of table types to include; null returns all
    * types
    * &return ResultSet each row is a table description
    * &see #getSearchStringEscape
    */
  public ResultSet getTables(String catalog, String schemaPattern,
                 String tableNamePattern, String types[]) throws
               SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData
                                    " + "are not yet implemented.");
  }

  /**
    * Get the schema names available in this database.  The results
    * are ordered by schema name.
    *
    * <P>The schema column is:
    *  <OL>
    *     <LI><B>TABLE_SCHEM</B> String => schema name
    *  </OL>
    *
    * &return ResultSet each row has a single String column that is a
    * schema name
    */
  public ResultSet getSchemas() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * Get the catalog names available in this database.  The results
    * are ordered by catalog name.
    *
    * <P>The catalog column is:
    *  <OL>
    *    <LI><B>TABLE_CAT</B> String => catalog name
    *  </OL>
    *
    * &return ResultSet each row has a single String column that is a
    * catalog name
    */
  public ResultSet getCatalogs() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                       "are not yet implemented.");
  }

  /**
    * Get the table types available in this database.  The results
    * are ordered by table type.
    *
    * &return ResultSet each row has a single String column that is a
    * table type
    */
  public ResultSet getTableTypes() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                      "are not yet implemented.");
  }

  /**
    * Get a description of table columns available in a catalog.
    *
    * <P>Only column descriptions matching the catalog, schema, table,
    * and column name criteria are returned. They are ordered by
    * TABLE_SCHEM, TABLE_NAME, and ORDINAL_POSITION.
    *
    * &param catalog a catalog name; "" retrieves those without a catalog
    * &param schemaPattern a schema name pattern; "" retrieves those
    * without a schema
    * &param tableNamePattern a table name pattern
    * &param columnNamePattern a column name pattern
    * &return ResultSet each row is a column description
    * &see #getSearchStringEscape
    */
  public ResultSet getColumns(String catalog, String schemaPattern,
                          String tableNamePattern, String
                        columnNamePattern) throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                      "are not yet implemented.");
  }

  /**
    * Get a description of the access rights for a table's columns.
    *
    * &param catalog a catalog name; "" retrieves those without a catalog
    * &param schema a schema name; "" retrieves those without a schema
    * &param table a table name
    * &param columnNamePattern a column name pattern
    * &return ResultSet each row is a column privilege description
    * &see #getSearchStringEscape
    */
  public ResultSet getColumnPrivileges(String catalog, String schema,
               String table, String columnNamePattern) throws
               SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData
                                     " + "are not yet implemented.");
  }

  /**
    * Get a description of the access rights for each table available
    * in a catalog.
    *
    * &param catalog a catalog name; "" retrieves those without a catalog
    * &param schemaPattern a schema name pattern; "" retrieves those
    * without a schema
    * &param tableNamePattern a table name pattern
    * &return ResultSet each row is a table privilege description
    * &see #getSearchStringEscape
    */
  public ResultSet getTablePrivileges(String catalog, String
              schemaPattern, String tableNamePattern) throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData
                                    " + "are not yet implemented.");
  }

  /**
    * Get a description of a table's optimal set of columns that
    * uniquely identifies a row. They are ordered by SCOPE.
    *
    * &param catalog a catalog name; "" retrieves those without a catalog
    * &param schema a schema name; "" retrieves those without a schema
    * &param table a table name
    * &param scope the scope of interest; use same values as SCOPE
    * &param nullable include columns that are nullable?
    * &return ResultSet each row is a column description
    */
  public ResultSet getBestRowIdentifier(String catalog, String schema,
                                 String table, int scope, boolean
                                nullable) throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                     "are not yet implemented.");
  }

  /**
    * Get a description of a table's columns that are automatically
    * updated when any value in a row is updated.  They are
    * unordered.
    *
    * &param catalog a catalog name; "" retrieves those without a catalog
    * &param schema a schema name; "" retrieves those without a schema
    * &param table a table name
    * &return ResultSet each row is a column description
    */
  public ResultSet getVersionColumns(String catalog, String schema,
                              String table) throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                     "are not yet implemented.");
  }

  /**
    * Get a description of a table's primary key columns.  They
    * are ordered by COLUMN_NAME.
    *
    * &param catalog a catalog name; "" retrieves those without a catalog
    * &param schema a schema name pattern; "" retrieves those
    * without a schema
    * &param table a table name
    * &return ResultSet each row is a primary key column description
    */
  public ResultSet getPrimaryKeys(String catalog, String schema,
                             String table) throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                      "are not yet implemented.");
  }

  /**
    * Get a description of the primary key columns that are
    * referenced by a table's foreign key columns (the primary keys
    * imported by a table).  They are ordered by PKTABLE_CAT,
    * PKTABLE_SCHEM, PKTABLE_NAME, and KEY_SEQ.
    *
    * &param catalog a catalog name; "" retrieves those without a catalog
    * &param schema a schema name pattern; "" retrieves those
    * without a schema
    * &param table a table name
    * &return ResultSet each row is a primary key column description
    * &see #getExportedKeys
    */
  public ResultSet getImportedKeys(String catalog, String schema,
                        String table) throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                      "are not yet implemented.");
  }

  /**
    * Get a description of foreign key columns that reference a
    * table's primary key columns (the foreign keys exported by a
    * table).  They are ordered by FKTABLE_CAT, FKTABLE_SCHEM,
    * FKTABLE_NAME, and KEY_SEQ.
    *
    * &param catalog a catalog name; "" retrieves those without a catalog
    * &param schema a schema name pattern; "" retrieves those
    * without a schema
    * &param table a table name
    * &return ResultSet each row is a foreign key column description
    * &see #getImportedKeys
    */
  public ResultSet getExportedKeys(String catalog, String schema,
                            String table) throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                      "are not yet implemented.");
  }

  /**
    * Get a description of the foreign key columns in the foreign key
    * table that reference the primary key columns of the primary key
    * table (describe how one table imports another's key.) This
    * should normally return a single foreign key/primary key pair
    * (most tables only import a foreign key from a table once.)  They
    * are ordered by FKTABLE_CAT, FKTABLE_SCHEM, FKTABLE_NAME, and
    * KEY_SEQ.
    *
    * &param catalog a catalog name; "" retrieves those without a catalog
    * &param schema a schema name pattern; "" retrieves those
    * without a schema
    * &param table a table name
    * &return ResultSet each row is a foreign key column description
    * &see #getImportedKeys
    */
  public ResultSet getCrossReference(String primaryCatalog, String
      primarySchema, String primaryTable,
                                   String foreignCatalog, String
                               foreignSchema, String foreignTable)
                                   throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                      "are not yet implemented.");
  }

  /**
    * Get a description of all the standard SQL types supported by
    * this database. They are ordered by DATA_TYPE and then by how
    * closely the data type maps to the corresponding JDBC SQL type.
    *
    * &return ResultSet each row is a SQL type description
    */
  public ResultSet getTypeInfo() throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData " +
                                      "are not yet implemented.");
  }

  /**
    * Get a description of a table's indices and statistics. They are
    * ordered by NON_UNIQUE, TYPE, INDEX_NAME, and ORDINAL_POSITION.
    *
    * &param catalog a catalog name; "" retrieves those without a catalog
    * &param schema a schema name pattern; "" retrieves those without a
    * schema
    * &param table a table name
    * &param unique when true, return only indices for unique values;
    * when false, return indices regardless of whether unique or not
    * &param approximate when true, result is allowed to reflect
    * approximate or out of data values; when false, results are requested
    * to be accurate
    * &return ResultSet each row is an index column description
    */
  public ResultSet getIndexInfo(String catalog, String schema, String
                        table, boolean unique, boolean approximate)
               throws SQLException {
    throw new SQLException("Many methods from DB2DatabaseMetaData  " +
                                       "are not yet implemented.");
  }
}

Listing C.5 DB2Statement.java.

/*    db2jdbc.sql.DB2Statement
 *
 *    Copyright (c) 1996 Heiner Braun
 *    Based on mSQL stuff by George Reese (borg&imaginary.com).
 *    Beft original comments; my comments are marked with _hb_.
 *    DB2 implementation of the JDBC Statement interface.
 */

package  db2jdbc.sql;

import   java.sql.SQLException;
import   java.sql.SQLWarning;
import   java.sql.ResultSet;
import   db2jdbc.sql.db2access.DB2CLI;
import   db2jdbc.sql.db2access.DB2CLIException;

public class DB2Statement implements java.sql.Statement {
  /**
    * A connection object to direct information to
    */
  private DB2Connection connection;
  /**
    * A result set returned from this query or whatever
    */
  private DB2ResultSet result;
  /**
    * The max field size for mSQL
    * NOTE: I have no idea what this should default to
    */
  private int max_field_size = 0;
  /**
    * The max rows supported by mSQL
    */
  private int max_rows = 0;
  /**
    * The number of seconds the driver will allow for a SQL statement to
    * execute before giving up; the default is to wait forever (0)
    */
  private int timeout = 0;
  /**
    * Constructs a new iMsqlStatement object.
    * &param conn the iMsqlConnection object
    */
  public DB2Statement(DB2Connection conn) {
    connection = conn;
  }

  /**
    * JDBC draft specification method to execute the specified SQL
    * query and gives back a result set.
    * &see java.sql.Statement#executeQuery
    * &exception SQLException raised for any MsqlException
    * &param sql the SQL statement string
    * &return the result set from the query
    */
  public ResultSet executeQuery(String sql)
       throws SQLException {
    result = null;
    // return new DB2ResultSet(connection.executeMsql(sql));

    // throws exception if necessary
    return new DB2ResultSet(connection.db2ExecSQL(sql));
  }

  /**
    * JDBC 0.54 specification method for executing simple UPDATE, INSERT,
    * DELETE, etc. statements which do not return ResultSet's.  The
    * return value is not particularly meaningful in mSQL since you cannot
    * get information on the number of rows affected by such an action
    * in mSQL.
    * &see java.sql.Statement#executeUpdate
    * &exception java.sql.SQLException thrown when an error occurs
    * executing the SQL
    * &return nr of rows
    */
  public int executeUpdate(String sql) throws SQLException {
    // _hb_ maybe like this?
    DB2CLI db2CLI;

    try {
      db2CLI = connection.db2ExecSQL(sql);
      return db2CLI.SQLRowCount();
    }
    catch( DB2CLIException e ) {
      db2CLI = null;
      throw new SQLException("DB2CLI exception: " + e.getMessage());
    }
  }

  /**
    * JDBC draft specification method to close off any open result sets
    * for this Statement.  This is a non-issue with mSQL, but portable
    * code should still be calling it.
    * &see java.sql.Statement#close
    */
  public void close() throws SQLException {
  }

  /**
    * JDBC draft specification method for getting the max field size
    * supported by mSQL.
    * &see java.sql.Statement#getMaxFieldSize
    * &return the value of max field size
    */
  public int getMaxFieldSize() throws SQLException {
    return max_field_size;
  }

  /**
    * JDBC draft specification method for setting the max field size.
    * &see java.sql.Statement#setMaxFieldSize
    * &param max the maximum field size
    */
  public void setMaxFieldSize(int max) throws SQLException {
    max_field_size = max;
  }

  /**
    * JDBC draft specification method for getting the max rows supported
    * by mSQL.
    * &see java.sql.Statement#getMaxRows
    * &return the maximum rows supported by mSQL
    */
  public int getMaxRows() throws SQLException {
    return max_rows;
  }

  /**
    * JDBC draft specification method for setting the max rows.
    * &see java.sql.Statement.setMaxRows
    * &param max the max rows
    */
  public void setMaxRows(int max) throws SQLException {
    max_rows = max;
  }

  /**
    * JDBC draft specification method for escape processing.
    * This boggles me.
    * &see java.sql.Statement#setEscapeProcessing
    * &param enable this does nothing right now
    */
  public void setEscapeProcessing(boolean enable)
       throws SQLException {
    throw new SQLException("No support for escape processing.");
  }

  /**
    * JDBC draft specification method for getting the query timeout, which
    * is the number of seconds the driver waits before giving up on the
    * query.
    * &see java.sql.Statement#getQueryTimeout
    * &see setQueryTimeout
    * &return the timeout value for this statement
    */
  public int getQueryTimeout() throws SQLException {
    return timeout;
  }

  /**
    * JDBC draft specification method for setting the query timeout.
    * &see java.sql.Statement#setQueryTimeout
    * &see getQueryTimeout
    * &param x the new query timeout value
    */
  public void setQueryTimeout(int x) throws SQLException {
    timeout = x;
  }

  /**
    * JDBC draft specification method for allowing one thread to cancel
    * this statement which may be running in another thread.  Right now,
    * there is nothing to cancel with mSQL JDBC.  Maybe I will make it do
    * something if I get actual processing in this class!
    * &see java.sql.Statement#cancel
    */
  public void cancel() {
  }

  /**
    * JDBC draft specification for getting the chain of warnings for this
    * statement.
    * &see java.sql.Statement#getWarnings
    * &return the chain of warnings
    */
  public final SQLWarning getWarnings() throws SQLException {
    return null;
  }

  /**
    * JDBC draft specification for clearing the warning chain.
    * &see java.sql.Statement#clearWarnings
    */
  public void clearWarnings() throws SQLException {
  }

  /**
    * JDBC 0.65 specification for setting cursor names.
    * mSQL does not support cursors.
    */
  public void setCursorName(String unused) throws SQLException {
    throw new SQLException("No support for cursors.");
  }
        //----------       Multiple Results        --------------

  /**
    * JDBC draft specification method to execute an SQL statement and
    * return true if a result set was gotten, false otherwise.  Note that
    * proper mSQL use of this method should always result in a
    * false return value.
    * &see java.sql.Statement#execute
    * &exception SQLException raised for any MsqlException encountered
    * &param sql the SQL to be executed
    * &return true if there is a result set available
    */
  public boolean execute(String sql) throws SQLException {
    throw new SQLException("No support for multiple result sets.");
  }

  /**
    * JDBC 0.54 specification method for obtaining a result set from a
    * statement object.
    * &see java.sql.Statement#getResultSet
    * &return null if no result set is available, otherwise a result set
    */
  public ResultSet getResultSet() throws SQLException {
    throw new SQLException("No support for multiple result sets.");
  }

  /**
    * Returns -1 always for mSQL.
    * &see java.sql.Statement#getUpdateCount
    * &return -1
    */
  public int getUpdateCount() throws SQLException {
    throw new SQLException("No support for multiple result sets.");
  }

  /**
    * JDBC 0.54 specification for determining if any more result sets
    * are left from a database statement.  Should always return false for
    * mSQL.
    * &see java.sql.Statement#getMoreResults
    * &return true if rows are to be gotten
    */
  public boolean getMoreResults() throws SQLException {
    throw new SQLException("No support for multiple result sets.");
  }
}

Listing C.6 DB2CLI.java.

/*    db2jdbc.sql.db2access.DB2CLI
 *
 *    Copyright (c) 1996 Heiner Braun
 *    braunhr&minnie.informatik.uni-stuttgart.de
 *
 *    This class provides the methods needed by the DB2 implementations
 *    of the JDBC interfaces. The file DB2CLIImpl contains the native C-
 *    code.
 *
 */

package db2jdbc.sql.db2access;

public class DB2CLI
{
  static {  System.loadLibrary("db2clijava"); }

  // Until now, every DB2CLI object supports only one statement.
  private long sql_henv = 0;
  private long sql_hdbc = 0;
  private long sql_hstmt = 0;
  private short sql_nresultcols = 0;
  private long[] sql_collen = new long[100];
  public DB2CLI() {
    //System.out.println("DB2CLI Object is created!");
  }
//---------------------------------------------------------------------
  // stuff for DB2Connection

  public native void getEnv() throws DB2CLIException;
  public native void freeEnv();

  public native void openConnection(String login,
                                            String passwd,
                                            String database) throws
                                            DB2CLIException;
  public native void closeConnection();
  public native void SQLExecQuery(String query) throws DB2CLIException;
  public native int SQLRowCount() throws DB2CLIException;
//---------------------------------------------------------------------
  // stuff for DB2ResultSetMetaData

  public int SQLNumResultCols() throws DB2CLIException {
    return (int) sql_nresultcols;
  }

  public native boolean ColSearchable(int column) throws DB2CLIException;
  public native boolean ColNullable(int column) throws DB2CLIException;
  public native int ColDisplaySize(int column) throws DB2CLIException;
  public native String ColLabel(int column) throws DB2CLIException;
  public native String ColName(int column) throws DB2CLIException;
  public native String ColSchemaName(int column) throws DB2CLIException;
  public native String ColTableName(int column) throws DB2CLIException;
  public native String ColCatalogName(int column) throws DB2CLIException;
  // see java.sql.Types
  public native int ColType(int column) throws DB2CLIException;
  public native String ColTypeName(int column) throws DB2CLIException;
//---------------------------------------------------------------------
  // stuff for DB2ResultSet

  public native boolean SQLFetch() throws DB2CLIException;
  public native String getString(int column) throws DB2CLIException;
}

Listing C.7 DB2CLIException.java.

package db2jdbc.sql.db2access;

public class DB2CLIException extends Exception {
  public DB2CLIException() { super(); }
  public DB2CLIException(String s) { super(s); }
}

Listing C.8 DB2CLIImpl.c.

/*---------------------------------------------------------------------
 *
 *    Copyright (c) 1996 Heiner Braun
 *         braunhr&minnie.informatik.uni-stuttgart.de
 *
 *     File:  DB2CLIImpl.c
 *               Contains native C methods for DB2CLI.java.
 *           Many code pieces were copied from the IBM DB2 CLI examples.
 *
 *
 */

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <javaString.h>
#include <StubPreamble.h>
#include "sqlcli1.h"
#include "db2jdbc_sql_db2access_DB2CLI.h"

#define  MAX_UID_LENGTH  18
#define  MAX_PWD_LENGTH  30
#define  MAX_STMT_LEN 255
#define  MAXCOLS   100

#ifndef max
#define  max(a,b) (a > b ? a : b)
#endif

void printErrorMsg(struct Hdb2jdbc_sql_db2access_DB2CLI *,
                char *, SQLRETURN);
/* ================================================================
 *
 * FUNCTIONS FOR DB2Connection
 *
 * ================================================================
 */

void db2jdbc_sql_db2access_DB2CLI_getEnv(struct Hdb2jdbc_sql_db2
  access_DB2CLI *this)
{
  SQLRETURN       rc;
  SQLHENV         henv;

  rc = SQLAllocEnv(&(henv));    /* allocate an environment handle    */
    unhand(this)->sql_henv = henv;

  if (rc != SQL_SUCCESS) {
      printErrorMsg(this, "Allocation of environment handle fails", rc);
    SignalError(0,
              "db2jdbc/sql/db2access/DB2CLIException",
                 "DB2CLI.getEnv: Allocation of environment handle fails.");
  }

  return;
}
/*---------------------------------------------------------------
 *
 *
 *
 */
void
db2jdbc_sql_db2access_DB2CLI_freeEnv(struct Hdb2jdbc_sql_db2access_DB2CLI
  *this)
{
  SQLHENV         henv;

  henv = unhand(this)->sql_henv;
  SQLFreeEnv(henv);

  return;
}
/*---------------------------------------------------------------------
 *
 *
 *
 */
void
db2jdbc_sql_db2access_DB2CLI_openConnection(struct Hdb2jdbc_sql_
  db2access_DB2CLI *this,
                                 struct Hjava_lang_String *login,
                                  struct Hjava_lang_String *passwd,
                                struct Hjava_lang_String
                                    *database)
{
  SQLRETURN       rc;
  SQLCHAR         uid[MAX_UID_LENGTH + 1];
  SQLCHAR         pwd[MAX_PWD_LENGTH + 1];
  SQLCHAR         db[SQL_MAX_DSN_LENGTH + 1];
  SQLHENV         henv;
  SQLHDBC         hdbc;

  if (!login || !passwd || !database) {
    SignalError(0,
               "db2jdbc/sql/db2access/
               DB2CLIException",
               "DB2CLI.openConnection: Wrong
                parameters.");
    return;
  }

  javaString2CString(login, uid, sizeof(uid));
  javaString2CString(passwd, pwd, sizeof(pwd));
  javaString2CString(database, db, sizeof(db));

  henv = unhand(this)->sql_henv;

  /* printf("DB2CLIImpl.openConnection henv: %li\n",henv); */

  /* allocate a connection handle     */
  rc = SQLAllocConnect(henv, &hdbc);
  if (rc != SQL_SUCCESS) {
    printErrorMsg(this, "ERROR while allocating a connection handle", rc);
    SignalError(0,
                "db2jdbc/sql/db2access/DB2CLIException",
                "DB2CLI.openConnection: ERROR while allocating a
                connection handle.");
    return;
  }

  unhand(this)->sql_hdbc = hdbc;

  /* Set AUTOCOMMIT ON */
  rc = SQLSetConnectOption(hdbc, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_ON);
  if (rc != SQL_SUCCESS) {
    printErrorMsg(this, "ERROR while setting AUTOCOMMIT ON", rc);
    SignalError(0,
                  "db2jdbc/sql/db2access/DB2CLIException",
                  "DB2CLI.openConnection: ERROR while setting AUTOCOMMIT
                  ON.");
    return;
  }

  /* printf("db: %s\nuid: %s\npwd: %s\n",db,uid,pwd); */
  rc = SQLConnect(hdbc, db, SQL_NTS, uid, SQL_NTS, pwd, SQL_NTS);
  if (rc != SQL_SUCCESS) {
      printErrorMsg(this, "Error while connecting to database", rc);
    SQLDisconnect(hdbc);
    SQLFreeConnect(hdbc);
    SignalError(0,
                   "db2jdbc/sql/db2access/DB2CLIException",
                   "DB2CLI.openConnection: ERROR while connecting to
                   database.");
    return;
  }

  /* printf("DB2CLIImpl.c openConnection: Connected...\n"); */

  return;
}
/*---------------------------------------------------------------------
 *
 *
 *
 */
void
db2jdbc_sql_db2access_DB2CLI_closeConnection(struct Hdb2jdbc_sql_
  db2access_DB2CLI *this)
{
  SQLHDBC         hdbc = unhand(this)->sql_hdbc;
  SQLDisconnect(hdbc);
  SQLFreeConnect(hdbc);
}
/*---------------------------------------------------------------------
 *
 *
 *
 */

void
db2jdbc_sql_db2access_DB2CLI_SQLExecQuery(struct Hdb2jdbc_sql_
  db2access_DB2CLI *this, struct Hjava_lang_String *query)
{
  SQLRETURN       rc;
  SQLINTEGER      displaysize;
  SQLSMALLINT     nresultcols;
  SQLCHAR         sqlstr[500];
  SQLHDBC         hdbc = unhand(this)->sql_hdbc;
  SQLHSTMT        hstmt;
  int             i;

  if (!query) {
    SignalError(0,
               "db2jdbc/sql/db2access/DB2CLIException",
               "DB2CLI.SQLExecQuery: Parameter error.");
    return;
  }

  javaString2CString(query, sqlstr, sizeof(sqlstr));

  /* printf("DB2CLIImpl.SQLExecQuery hdbc: %li\n",hdbc); */

  SQLAllocStmt(hdbc, &hstmt); /* allocate a statement handle */

  unhand(this)->sql_hstmt = hstmt;

  /* printf("DB2CLIImpl.SQLExecQuery hstmt: %li\n",hstmt); */

  rc = SQLExecDirect(hstmt, sqlstr, SQL_NTS);
  if (rc != SQL_SUCCESS) {
      printErrorMsg(this, "Error while executing SQL query", rc);
    SQLFreeStmt(hstmt, SQL_DROP);
      SignalError(0,
                 "db2jdbc/sql/db2access/DB2CLIException",
                 "DB2CLI.SQLExecQuery: Error while executing SQL query.");
    return;
  }

  rc = SQLNumResultCols(hstmt, &nresultcols);
  if (rc != SQL_SUCCESS) {
      printErrorMsg(this, "SQLNumResultCols fails", rc);
    SQLFreeStmt(hstmt, SQL_DROP);
      SignalError(0,
                 "db2jdbc/sql/db2access/DB2CLIException",
                 "DB2CLI.SQLExecQuery: SQLNumResultCols fails.");
    return;
  }

  unhand(this)->sql_nresultcols = nresultcols;

  for (i = 0; i < nresultcols; i++) {

    /* get display length for column. */
    SQLColAttributes(hstmt, i + 1, SQL_COLUMN_DISPLAY_SIZE, NULL, 0,
                                        NULL, &displaysize);
    (unhand(unhand(this)->sql_collen)->body)[i] = displaysize + 1;
  }

  return;
}
/*---------------------------------------------------------------------
 *
 *
 *
 */
long
db2jdbc_sql_db2access_DB2CLI_SQLRowCount(struct Hdb2jdbc_sql_
  db2access_DB2CLI *this)
{
  SQLRETURN       rc;
  SQLINTEGER      rowcount;
  SQLHSTMT        hstmt = unhand(this)->sql_hstmt;

  rc = SQLRowCount(hstmt, &rowcount);
  if (rc != SQL_SUCCESS) {
    printErrorMsg(this, "Nr of rows could not be received.", rc);
    SignalError(0,
                 "db2jdbc/sql/db2access/DB2CLIException",
                 "DB2CLI.SQLRowCount: Nr of rows could not be
                 received.");
    return 0;
  }

  return (long) rowcount;
}
/* ================================================================
 *
 * FUNCTIONS FOR DB2ResultSetMetaData
 *
 * ================================================================
 */
/*---------------------------------------------------------------------
 *
 *
 *
 */
long
db2jdbc_sql_db2access_DB2CLI_ColSearchable(struct
Hdb2jdbc_sql_db2access_DB2CLI *this, long column)
{
  SQLRETURN       rc;
  SQLINTEGER      searchable;
  SQLHSTMT        hstmt = unhand(this)->sql_hstmt;

  rc = SQLColAttributes(hstmt, column, SQL_COLUMN_SEARCHABLE,
                                     NULL, 0, NULL, &searchable);

  if (rc != SQL_SUCCESS) {
      printErrorMsg(this, "SQLColAttributes fails", rc);
    SignalError(0, "db2jdbc/sql/db2access/DB2CLIException",
                 "DB2CLI.ColSearchable: SQLColAttributes fails.");
    return (long) 0;
  }
  if (searchable == SQL_SEARCHABLE)   return (long) 0;
  else                                return (long) 1;
}
/*---------------------------------------------------------------------
 *
 *
 *
 */
long
db2jdbc_sql_db2access_DB2CLI_ColNullable(struct Hdb2jdbc_sql_
  db2access_DB2CLI *this, long column)
{
  SQLRETURN       rc;
  SQLINTEGER      nullable;
  SQLHSTMT        hstmt = unhand(this)->sql_hstmt;

  rc = SQLColAttributes(hstmt, column, SQL_COLUMN_NULLABLE,
                                       NULL, 0, NULL, &nullable);

  if (rc != SQL_SUCCESS) {
      printErrorMsg(this, "SQLColAttributes fails", rc);
    SignalError(0, "db2jdbc/sql/db2access/DB2CLIException",
                 "DB2CLI.ColNullable: SQLColAttributes fails.");
    return (long) 0;
  }
  if (nullable == SQL_NULLABLE)   return (long) 0;
  else                            return (long) 1;
}
/*---------------------------------------------------------------------
 *
 *
 *
 */
long
db2jdbc_sql_db2access_DB2CLI_ColDisplaySize(struct Hdb2jdbc_sql_
  db2access_DB2CLI *this,long column)
{
  SQLRETURN       rc;
  SQLINTEGER      displaySize;
  SQLHSTMT        hstmt = unhand(this)->sql_hstmt;

  rc = SQLColAttributes(hstmt, column, SQL_COLUMN_DISPLAY_SIZE,
                                      NULL, 0, NULL, &displaySize);

  if (rc != SQL_SUCCESS) {
      printErrorMsg(this, "SQLColAttributes fails", rc);
    SignalError(0, "db2jdbc/sql/db2access/DB2CLIException",
                "DB2CLI.ColDisplaySize: SQLColAttributes fails.");
    return (long) 0;
  }

   return (long) displaySize;
}

/*---------------------------------------------------------------------
 *
 *
 *
 */
Hjava_lang_String *
db2jdbc_sql_db2access_DB2CLI_ColLabel(struct Hdb2jdbc_sql_
  db2access_DB2CLI *this, long column)
{
  SQLRETURN       rc;
  SQLCHAR         retString[SQL_MAX_DSN_LENGTH];
  SQLSMALLINT     length;
  SQLHSTMT        hstmt = unhand(this)->sql_hstmt;

  rc = SQLColAttributes(hstmt, column, SQL_COLUMN_LABEL,
                        retString, sizeof(retString), &length, 0);

  if (rc != SQL_SUCCESS) {
      printErrorMsg(this, "SQLColAttributes fails", rc);
    SignalError(0, "db2jdbc/sql/db2access/DB2CLIException",
                  "DB2CLI.ColLabel: SQLColAttributes fails.");
  }

  return makeJavaString(retString, strlen(retString));
}
/*---------------------------------------------------------------------
 *
 *
 *
 */
Hjava_lang_String *
db2jdbc_sql_db2access_DB2CLI_ColName(struct Hdb2jdbc_sql_db2access_DB2CLI
  *this, long column)
{
  SQLRETURN       rc;
  SQLCHAR         retString[SQL_MAX_DSN_LENGTH];
  SQLSMALLINT     length;
  SQLHSTMT        hstmt = unhand(this)->sql_hstmt;

  rc = SQLColAttributes(hstmt, column, SQL_COLUMN_NAME,
                        retString, sizeof(retString), &length, 0);

  if (rc != SQL_SUCCESS) {
    printErrorMsg(this, "SQLColAttributes fails", rc);
    SignalError(0, "db2jdbc/sql/db2access/DB2CLIException",
                 "DB2CLI.ColName: SQLColAttributes fails.");
  }

  return makeJavaString(retString, strlen(retString));
}
/*---------------------------------------------------------------------
 *
 *
 *
 */
Hjava_lang_String *
db2jdbc_sql_db2access_DB2CLI_ColSchemaName(struct Hdb2jdbc_sql_
  db2access_DB2CLI *this, long column)
{
  SQLRETURN       rc;
  SQLCHAR         retString[SQL_MAX_DSN_LENGTH];
  SQLSMALLINT     length;
  SQLHSTMT        hstmt = unhand(this)->sql_hstmt;

  rc = SQLColAttributes(hstmt, column, SQL_COLUMN_SCHEMA_NAME,
                        retString, sizeof(retString), &length, 0);

  if (rc != SQL_SUCCESS) {
      printErrorMsg(this, "SQLColAttributes fails", rc);
    SignalError(0, "db2jdbc/sql/db2access/DB2CLIException",
                "DB2CLI.ColSchemaName: SQLColAttributes fails.");
  }

  return makeJavaString(retString, strlen(retString));
}
/*---------------------------------------------------------------------
 *
 *
 *
 */
Hjava_lang_String *
db2jdbc_sql_db2access_DB2CLI_ColTableName(struct Hdb2jdbc_sql_
  db2access_DB2CLI *this, long column)
{
  SQLRETURN       rc;
  SQLCHAR         retString[SQL_MAX_DSN_LENGTH];
  SQLSMALLINT     length;
  SQLHSTMT        hstmt = unhand(this)->sql_hstmt;

  rc = SQLColAttributes(hstmt, column, SQL_COLUMN_TABLE_NAME,
                        retString, sizeof(retString), &length, 0);

  if (rc != SQL_SUCCESS) {
      printErrorMsg(this, "SQLColAttributes fails", rc);
    SignalError(0, "db2jdbc/sql/db2access/DB2CLIException",
                "DB2CLI.ColTableName: SQLColAttributes fails.");
  }

  return makeJavaString(retString, strlen(retString));
}
/*---------------------------------------------------------------------
 *
 *
 *
 */
Hjava_lang_String *
db2jdbc_sql_db2access_DB2CLI_ColCatalogName(struct Hdb2jdbc_sql_
  db2access_DB2CLI *this, long column)
{
  SQLRETURN       rc;
  SQLCHAR         retString[SQL_MAX_DSN_LENGTH];
  SQLSMALLINT     length;
  SQLHSTMT        hstmt = unhand(this)->sql_hstmt;

  rc = SQLColAttributes(hstmt, column, SQL_COLUMN_CATALOG_NAME,
                        retString, sizeof(retString), &length, 0);

  if (rc != SQL_SUCCESS) {
      printErrorMsg(this, "SQLColAttributes fails", rc);
    SignalError(0, "db2jdbc/sql/db2access/DB2CLIException",
                "DB2CLI.ColCatalogName: SQLColAttributes fails.");
  }

  return makeJavaString(retString, strlen(retString));
}
/*---------------------------------------------------------------------
 *
 *
 *
 */
long
db2jdbc_sql_db2access_DB2CLI_ColType(struct Hdb2jdbc_sql_db2access_DB2CLI
  *this, long column)
{
  SQLRETURN       rc;
  SQLINTEGER      type;
  SQLHSTMT        hstmt = unhand(this)->sql_hstmt;

  rc = SQLColAttributes(hstmt, column, SQL_COLUMN_TYPE,
                                            NULL, 0, NULL, &type);

  if (rc != SQL_SUCCESS) {
      printErrorMsg(this, "SQLColAttributes fails", rc);
    SignalError(0, "db2jdbc/sql/db2access/DB2CLIException",
                "DB2CLI.ColType: SQLColAttributes fails.");
    return (long) 0;
  }

  /* match DB2 SQL types to JDBC types in java.sql.Types */
  switch (type) {
    case SQL_CHAR :          return 1;   break;
    case SQL_NUMERIC :       return 2;   break;
    case SQL_DECIMAL :       return 3;   break;
    case SQL_INTEGER :       return 4;   break;
    case SQL_SMALLINT :      return 5;   break;
    case SQL_FLOAT :         return 6;   break;
    case SQL_REAL :          return 7;   break;
    case SQL_DOUBLE :        return 8;   break;
    case SQL_DATE :          return 91;  break;
    case SQL_TIME :          return 92;  break;
    case SQL_TIMESTAMP :     return 93;  break;
    case SQL_VARCHAR :       return 12;  break;
    case SQL_LONGVARCHAR :   return -1;  break;
    case SQL_BINARY :        return -2;  break;
    case SQL_VARBINARY :     return -3;  break;
    case SQL_LONGVARBINARY : return -4;  break;
    case SQL_BIGINT :        return -5;  break;
    case SQL_TINYINT :       return -6;  break;
    case SQL_BIT :           return -7;  break;
    default :                return 1111; break;
  }
}

/*---------------------------------------------------------------------
 *
 *
 *
 */
Hjava_lang_String *
db2jdbc_sql_db2access_DB2CLI_ColTypeName(struct Hdb2jdbc_sql_
  db2access_DB2CLI *this, long column)
{
  SQLRETURN       rc;
  SQLCHAR         retString[SQL_MAX_DSN_LENGTH];
  SQLSMALLINT     length;
  SQLHSTMT        hstmt = unhand(this)->sql_hstmt;

  rc = SQLColAttributes(hstmt, column, SQL_COLUMN_TYPE_NAME,
                        retString, sizeof(retString), &length, 0);

  if (rc != SQL_SUCCESS) {
      printErrorMsg(this, "SQLColAttributes fails", rc);
    SignalError(0, "db2jdbc/sql/db2access/DB2CLIException",
                "DB2CLI.ColTypeName: SQLColAttributes fails.");
  }

  return makeJavaString(retString, strlen(retString));
}
/* ================================================================
 *
 * FUNCTIONS FOR DB2ResultSet
 *
 * ================================================================
 */

/*---------------------------------------------------------------------
 *
 *
 *
 */
long
db2jdbc_sql_db2access_DB2CLI_SQLFetch(struct Hdb2jdbc_sql_
  db2access_DB2CLI *this)
{
  SQLRETURN       rc;
  SQLHSTMT        hstmt = unhand(this)->sql_hstmt;
  SQLSMALLINT     nresultcols = unhand(this)->sql_nresultcols;

  if ((rc = SQLFetch(hstmt)) == SQL_SUCCESS) {
    return (long) 1;
  } else {

    SQLFreeStmt(hstmt, SQL_DROP); /* free statement handle */

    if (rc != SQL_NO_DATA_FOUND) {
        printErrorMsg(this, "SQLFetch fails", rc);
      SignalError(0, "db2jdbc/sql/db2access/DB2CLIException",
                  "DB2CLI.SQLFetch: SQLFetch fails.");
    }

    return (long) 0;
  }
}

/*---------------------------------------------------------------------
 *
 *
 *
 */
Hjava_lang_String *
db2jdbc_sql_db2access_DB2CLI_getString(struct Hdb2jdbc_sql_
  db2access_DB2CLI *this, long column)
{
  SQLRETURN       rc;
  SQLINTEGER      collen = (unhand(unhand(this)->sql_collen)-
    >body)[column - 1];
  SQLCHAR        *retString;
  SQLHSTMT        hstmt = unhand(this)->sql_hstmt;
  SQLINTEGER      length;

    retString = (SQLCHAR *) malloc((int)collen);

  rc = SQLGetData(hstmt, (SQLUSMALLINT)column, SQL_C_CHAR,
                                      retString, collen, &length);
  if (rc != SQL_SUCCESS) {
      printErrorMsg(this, "SQLGetData fails", rc);
    SignalError(0, "db2jdbc/sql/db2access/DB2CLIException",
                "DB2CLI.getString: SQLGetData fails.");
  }

  return makeJavaString(retString, strlen(retString));
}

/* ================================================================
 *
 * LOCAL FUNCTIONS
 *
 * ================================================================
 */

/*---------------------------------------------------------------------
 *
 *
 *
 */
void printErrorMsg(struct Hdb2jdbc_sql_db2access_DB2CLI *this,
         char *msg, SQLRETURN rc)
{
  SQLCHAR         buffer[SQL_MAX_MESSAGE_LENGTH + 1];
  SQLCHAR         sqlstate[SQL_SQLSTATE_SIZE + 1];
  SQLINTEGER      sqlcode;
  SQLSMALLINT     length;
  SQLHENV         henv = unhand(this)->sql_henv;
  SQLHDBC         hdbc = unhand(this)->sql_hdbc;
  SQLHSTMT        hstmt = unhand(this)->sql_hstmt;

  printf("DB2CLIImpl.c: %s\n", msg);

  switch (rc) {

  case SQL_SUCCESS:
    break;
  case SQL_INVALID_HANDLE:
    printf("    SQLRETURN indicates: Invalid Handle\n");
    break;
  case SQL_ERROR:
    printf("    SQLRETURN indicates: FATAL ERROR\n");
    break;
  case SQL_SUCCESS_WITH_INFO:
    printf("    SQLRETURN indicates: Warning Message\n");
    break;
  case SQL_NO_DATA_FOUND:
    printf("    SQLRETURN indicates: No Data Found\n");
    break;
  default:
    printf("                Unknown Return Code\n");
  }

  while (SQLError(henv, hdbc, hstmt, sqlstate, &sqlcode, buffer,
                 SQL_MAX_MESSAGE_LENGTH + 1, &length) == SQL_SUCCESS) {
              printf("    ----------------------------------\n");
    printf("    SQLSTATE: %s\n", sqlstate);
    printf("    Native Error Code: %ld\n", sqlcode);
    printf("    %s \n", buffer);
  };

  return;
}


Table of Contents